diff --git a/.codacy/codacy.yaml b/.codacy/codacy.yaml index d75cea10..9762e4ac 100644 --- a/.codacy/codacy.yaml +++ b/.codacy/codacy.yaml @@ -8,3 +8,4 @@ tools: - pylint@3.3.6 - pmd@6.55.0 - dartanalyzer@3.7.2 + - semgrep@1.78.0 \ No newline at end of file diff --git a/.gitignore b/.gitignore index 1b7481d8..5d99153d 100644 --- a/.gitignore +++ b/.gitignore @@ -31,3 +31,6 @@ codacy-cli #Ignore cursor AI rules .cursor/rules/codacy.mdc + +#Macos +.DS_Store diff --git a/cmd/analyze.go b/cmd/analyze.go index faf212a1..4cc0a153 100644 --- a/cmd/analyze.go +++ b/cmd/analyze.go @@ -222,6 +222,15 @@ func runDartAnalyzer(workDirectory string, pathsToCheck []string, outputFile str return tools.RunDartAnalyzer(workDirectory, dartanalyzer.InstallDir, dartanalyzer.Binaries["dart"], pathsToCheck, outputFile, outputFormat) } +func runSemgrepAnalysis(workDirectory string, pathsToCheck []string, outputFile string, outputFormat string) error { + semgrep := config.Config.Tools()["semgrep"] + if semgrep == nil { + log.Fatal("Semgrep tool configuration not found") + } + + return tools.RunSemgrep(workDirectory, semgrep, pathsToCheck, outputFile, outputFormat) +} + var analyzeCmd = &cobra.Command{ Use: "analyze", Short: "Runs all configured linters.", @@ -312,6 +321,8 @@ func runTool(workDirectory string, toolName string, args []string, outputFile st return runPmdAnalysis(workDirectory, args, outputFile, outputFormat) case "pylint": return runPylintAnalysis(workDirectory, args, outputFile, outputFormat) + case "semgrep": + return runSemgrepAnalysis(workDirectory, args, outputFile, outputFormat) case "dartanalyzer": return runDartAnalyzer(workDirectory, args, outputFile, outputFormat) default: diff --git a/cmd/init.go b/cmd/init.go index eb003665..7f77f38b 100644 --- a/cmd/init.go +++ b/cmd/init.go @@ -146,6 +146,7 @@ func configFileTemplate(tools []tools.Tool) string { PyLint: "3.3.6", PMD: "6.55.0", DartAnalyzer: "3.7.2", + Semgrep: "1.78.0", } // Build map of enabled tools with their versions @@ -200,6 +201,7 @@ func configFileTemplate(tools []tools.Tool) string { PyLint: "pylint", PMD: "pmd", DartAnalyzer: "dartanalyzer", + Semgrep: "semgrep", } for uuid, name := range uuidToName { @@ -214,6 +216,7 @@ func configFileTemplate(tools []tools.Tool) string { sb.WriteString(fmt.Sprintf(" - pylint@%s\n", defaultVersions[PyLint])) sb.WriteString(fmt.Sprintf(" - pmd@%s\n", defaultVersions[PMD])) sb.WriteString(fmt.Sprintf(" - dartanalyzer@%s\n", defaultVersions[DartAnalyzer])) + sb.WriteString(fmt.Sprintf(" - semgrep@%s\n", defaultVersions[Semgrep])) } return sb.String() @@ -266,7 +269,8 @@ func buildRepositoryConfigurationFiles(token string) error { // Only generate config files for tools not using their own config file for _, tool := range configuredToolsWithUI { - url := fmt.Sprintf("%s/api/v3/analysis/organizations/%s/%s/repositories/%s/tools/%s/patterns?enabled=true", + + url := fmt.Sprintf("%s/api/v3/analysis/organizations/%s/%s/repositories/%s/tools/%s/patterns?enabled=true&limit=1000", CodacyApiBase, initFlags.provider, initFlags.organization, @@ -396,6 +400,13 @@ func createToolFileConfigurations(tool tools.Tool, patternConfiguration []domain return fmt.Errorf("failed to create Dart Analyzer config: %v", err) } } + case Semgrep: + if len(patternConfiguration) > 0 { + err := createSemgrepConfigFile(patternConfiguration, toolsConfigDir) + if err != nil { + return fmt.Errorf("failed to create Semgrep config: %v", err) + } + } } return nil } @@ -456,6 +467,24 @@ func createDefaultEslintConfigFile(toolsConfigDir string) error { return os.WriteFile(filepath.Join(toolsConfigDir, "eslint.config.mjs"), []byte(content), utils.DefaultFilePerms) } +// SemgrepRulesFile represents the structure of the rules.yaml file +type SemgrepRulesFile struct { + Rules []map[string]interface{} `yaml:"rules"` +} + +// createSemgrepConfigFile creates a semgrep.yaml configuration file based on the API configuration +func createSemgrepConfigFile(config []domain.PatternConfiguration, toolsConfigDir string) error { + // Use the refactored function from tools package + configData, err := tools.GetSemgrepConfig(config) + + if err != nil { + return fmt.Errorf("failed to create Semgrep config: %v", err) + } + + // Write to file + return os.WriteFile(filepath.Join(toolsConfigDir, "semgrep.yaml"), configData, utils.DefaultFilePerms) +} + // cleanConfigDirectory removes all previous configuration files in the tools-configs directory func cleanConfigDirectory(toolsConfigDir string) error { // Check if directory exists @@ -489,4 +518,5 @@ const ( PMD string = "9ed24812-b6ee-4a58-9004-0ed183c45b8f" PyLint string = "31677b6d-4ae0-4f56-8041-606a8d7a8e61" DartAnalyzer string = "d203d615-6cf1-41f9-be5f-e2f660f7850f" + Semgrep string = "6792c561-236d-41b7-ba5e-9d6bee0d548b" ) diff --git a/domain/patternConfiguration.go b/domain/patternConfiguration.go index 14d7961c..ffa65786 100644 --- a/domain/patternConfiguration.go +++ b/domain/patternConfiguration.go @@ -6,12 +6,22 @@ type ParameterConfiguration struct { } type PatternDefinition struct { - Id string `json:"id"` - Category string `json:"category"` - Level string `json:"level"` + Id string `json:"id"` + Category string `json:"category"` + Level string `json:"level"` + SeverityLevel string `json:"severityLevel"` + Enabled bool `json:"enabled"` + Parameters []ParameterConfiguration `json:"parameters"` + Title string `json:"title"` + Description string `json:"description"` + Explanation string `json:"explanation"` + Languages []string `json:"languages"` + TimeToFix int `json:"timeToFix"` } type PatternConfiguration struct { PatternDefinition PatternDefinition `json:"patternDefinition"` Parameters []ParameterConfiguration + Enabled bool `json:"enabled"` + IsCustom bool `json:"isCustom"` } diff --git a/plugins/tool-utils_test.go b/plugins/tool-utils_test.go index ef7add91..6375c6e7 100644 --- a/plugins/tool-utils_test.go +++ b/plugins/tool-utils_test.go @@ -167,6 +167,7 @@ func TestGetSupportedTools(t *testing.T) { "pylint", "trivy", "dartanalyzer", + "semgrep", }, expectedError: false, }, diff --git a/plugins/tools/semgrep/plugin.yaml b/plugins/tools/semgrep/plugin.yaml new file mode 100644 index 00000000..f6ed99ef --- /dev/null +++ b/plugins/tools/semgrep/plugin.yaml @@ -0,0 +1,16 @@ +name: semgrep +description: Static Analysis Security Testing (SAST) tool +runtime: python +runtime_binaries: + package_manager: python3 + execution: python3 +binaries: + - name: python + path: "venv/bin/python3" +formatters: + - name: json + flag: "--json" +output_options: + file_flag: "--output" +analysis_options: + default_path: "." diff --git a/plugins/tools/semgrep/rules.yaml b/plugins/tools/semgrep/rules.yaml new file mode 100644 index 00000000..2cda3d97 --- /dev/null +++ b/plugins/tools/semgrep/rules.yaml @@ -0,0 +1,113938 @@ +rules: +- id: ai.csharp.detect-openai.detect-openai + languages: + - csharp + severity: INFO + message: "Possibly found usage of AI: OpenAI" + pattern-either: + - pattern: using OpenAI + - pattern: (ChatClient $CLIENT) + - pattern: (ChatClient $CLIENT).$FUNC(...) + metadata: + references: + - http://semgrep.dev/blog/2024/detecting-shadow-ai + category: maintainability + technology: + - genAI + - LLMs + confidence: LOW +- id: ai.dart.detect-gemini.detect-gemini + languages: + - dart + severity: INFO + message: "Possibly found usage of AI: Gemini" + pattern-either: + - pattern: import 'package:google_generative_ai'; + - pattern: final $MODEL = GenerativeModel(...); + metadata: + references: + - http://semgrep.dev/blog/2024/detecting-shadow-ai + category: maintainability + technology: + - genAI + - LLMs + confidence: LOW +- id: ai.go.detect-gemini.detect-gemini + languages: + - go + severity: INFO + message: "Possibly found usage of AI: Gemini" + pattern-either: + - pattern: import "github.com/google/generative-ai-go" + - pattern: genai.NewClient(...) + metadata: + references: + - http://semgrep.dev/blog/2024/detecting-shadow-ai + category: maintainability + technology: + - genAI + - LLMs + confidence: LOW +- id: ai.go.detect-openai.detect-openai + languages: + - go + severity: INFO + message: "Possibly found usage of AI: OpenAI" + pattern-either: + - pattern: import "github.com/sashabaranov/go-openai" + - pattern: gogpt.NewClient(...) + metadata: + references: + - http://semgrep.dev/blog/2024/detecting-shadow-ai + category: maintainability + technology: + - genAI + - LLMs + confidence: LOW +- id: ai.kotlin.detect-gemini.detect-gemini + languages: + - kotlin + severity: INFO + message: "Possibly found usage of AI: Gemini" + pattern-either: + - pattern: import com.google.ai + - pattern: GenerativeModel(...) + metadata: + references: + - http://semgrep.dev/blog/2024/detecting-shadow-ai + category: maintainability + technology: + - genAI + - LLMs + confidence: LOW +- id: ai.python.detect-anthropic.detect-anthropic + languages: + - python + severity: INFO + message: "Possibly found usage of AI: Anthropic" + pattern-either: + - pattern: import anthropic + - pattern: from anthropic import $ANYTHING + - pattern: Anthropic(...) + - pattern: anthropic.Anthropic(...) + - pattern: $CLIENT.messages.$FUNC(...,model=...,...) + metadata: + references: + - http://semgrep.dev/blog/2024/detecting-shadow-ai + category: maintainability + technology: + - genAI + - LLMs + confidence: LOW +- id: ai.python.detect-gemini.detect-gemini + languages: + - python + severity: INFO + message: "Possibly found usage of AI: Gemini" + pattern-either: + - pattern: import google.generativeai + metadata: + references: + - http://semgrep.dev/blog/2024/detecting-shadow-ai + category: maintainability + technology: + - genAI + - LLMs + confidence: LOW +- id: ai.python.detect-huggingface.detect-huggingface + languages: + - python + severity: INFO + message: "Possibly found usage of AI: HuggingFace" + pattern-either: + - pattern: import huggingface_hub + metadata: + references: + - http://semgrep.dev/blog/2024/detecting-shadow-ai + category: maintainability + technology: + - genAI + - LLMs + confidence: LOW +- id: ai.python.detect-langchain.detect-langchain + languages: + - python + severity: INFO + message: "Possibly found usage of AI tooling: LangChain" + pattern-either: + - pattern: import langchain_openai + - pattern: ChatOpenAI(...) + - pattern: import langchain_community + - pattern: Ollama(...) + - pattern: import langchain_anthropic + - pattern: ChatAnthropic(...) + - pattern: import langchain_cohere + - pattern: ChatCohere(...) + - pattern: import langchain_core + - pattern: import langchain + metadata: + references: + - http://semgrep.dev/blog/2024/detecting-shadow-ai + category: maintainability + technology: + - genAI + - LLMs + confidence: LOW +- id: ai.python.detect-mistral.detect-mistral + languages: + - python + severity: INFO + message: "Possibly found usage of AI: Mistral" + pattern-either: + - pattern: import mistralai + - pattern: MistralClient(...) + - pattern: $CLIENT.chat(...,model=...,...) + metadata: + references: + - http://semgrep.dev/blog/2024/detecting-shadow-ai + category: maintainability + technology: + - genAI + - LLMs + confidence: LOW +- id: ai.python.detect-openai.detect-openai + languages: + - python + severity: INFO + message: "Possibly found usage of AI: OpenAI" + pattern-either: + - pattern: import openai + - pattern: from openai import $ANYTHING + - pattern: OpenAI(...) + - pattern: $CLIENT.chat.completions.$FUNC(...) + metadata: + references: + - http://semgrep.dev/blog/2024/detecting-shadow-ai + category: maintainability + technology: + - genAI + - LLMs + confidence: LOW +- id: ai.python.detect-pytorch.detect-pytorch + languages: + - python + severity: INFO + message: "Possibly found usage of AI tooling: PyTorch" + pattern-either: + - pattern: import torch + - pattern: torch.$FUNC(...) + metadata: + references: + - http://semgrep.dev/blog/2024/detecting-shadow-ai + category: maintainability + technology: + - genAI + - LLMs + confidence: LOW +- id: ai.python.detect-tensorflow.detect-tensorflow + languages: + - python + severity: INFO + message: "Possibly found usage of AI tooling: Tensorflow" + pattern-either: + - pattern: import tensorflow + metadata: + references: + - http://semgrep.dev/blog/2024/detecting-shadow-ai + category: maintainability + technology: + - genAI + - LLMs + confidence: LOW +- id: ai.swift.detect-apple-core-ml.detect-apple-core-ml + languages: + - swift + severity: INFO + message: "Possibly found usage of AI: Apple CoreML" + pattern-either: + - pattern: VNCoreMLModel(...) + - pattern: MLModelConfiguration(...) + metadata: + references: + - http://semgrep.dev/blog/2024/detecting-shadow-ai + category: maintainability + technology: + - genAI + - LLMs + confidence: LOW +- id: ai.swift.detect-gemini.detect-gemini + languages: + - swift + severity: INFO + message: "Possibly found usage of AI: Gemini" + pattern-either: + - pattern: import GoogleGenerativeAI + - pattern: GenerativeModel(...) + metadata: + references: + - http://semgrep.dev/blog/2024/detecting-shadow-ai + category: maintainability + technology: + - genAI + - LLMs + confidence: LOW +- id: ai.typescript.detect-anthropic.detect-anthropic + languages: + - js + - ts + severity: INFO + message: "Possibly found usage of AI: Anthropic" + pattern-either: + - pattern: import "@anthropic-ai" + - pattern: import $ANYTHING from "@anthropic-ai"; + - pattern: new Anthropic(...) + - pattern: anthropic.messages.$FUNC(...) + metadata: + references: + - http://semgrep.dev/blog/2024/detecting-shadow-ai + category: maintainability + technology: + - genAI + - LLMs + confidence: LOW +- id: ai.typescript.detect-gemini.detect-gemini + languages: + - js + - ts + severity: INFO + message: "Possibly found usage of AI: Gemini" + pattern-either: + - pattern: import "@google/generative-ai" + - pattern: import $ANYTHING from "@google/generative-ai"; + - pattern: new GoogleGenerativeAI(...) + - pattern: $GENAI.getGenerativeModel(...) + metadata: + references: + - http://semgrep.dev/blog/2024/detecting-shadow-ai + category: maintainability + technology: + - genAI + - LLMs + confidence: LOW +- id: ai.typescript.detect-mistral.detect-mistral + languages: + - js + - ts + severity: INFO + message: "Possibly found usage of AI: Mistral" + pattern-either: + - pattern: import "@mistralai" + - pattern: new MistralClient(...) + - pattern: |- + $CLIENT.chat({model: ...}) + metadata: + references: + - http://semgrep.dev/blog/2024/detecting-shadow-ai + category: maintainability + technology: + - genAI + - LLMs + confidence: LOW +- id: ai.typescript.detect-openai.detect-openai + languages: + - js + - ts + severity: INFO + message: "Possibly found usage of AI: OpenAI" + pattern-either: + - pattern: import "openai" + - pattern: import $ANYTHING from "openai"; + - pattern: new OpenAI(...) + - pattern: $CLIENT.chat.completions.$FUNC(...) + metadata: + references: + - http://semgrep.dev/blog/2024/detecting-shadow-ai + category: maintainability + technology: + - genAI + - LLMs + confidence: LOW +- id: ai.typescript.detect-promptfoo.detect-promptfoo + languages: + - js + - ts + severity: INFO + message: "Possibly found usage of AI tooling: promptfoo" + pattern-either: + - pattern: import "promptfoo" + - pattern: promptfoo.evaluate(...) + metadata: + references: + - http://semgrep.dev/blog/2024/detecting-shadow-ai + category: maintainability + technology: + - genAI + - LLMs + confidence: LOW +- id: ai.typescript.detect-vercel-ai.detect-vercel-ai + languages: + - js + - ts + severity: INFO + message: "Possibly found usage of AI: VercelAI" + pattern-either: + - pattern: import "ai" + - pattern: import "@ai-sdk" + - pattern: generateText({model:...}) + - pattern: generateText({prompt:...}) + metadata: + references: + - http://semgrep.dev/blog/2024/detecting-shadow-ai + category: maintainability + technology: + - genAI + - LLMs + confidence: LOW +- id: apex.lang.best-practice.ncino.accessmodifiers.globalaccessmodifiers.global-access-modifiers + min-version: 1.44.0 + severity: WARNING + languages: + - apex + metadata: + cwe: + - 'CWE-284: Improper Access Control' + category: best-practice + technology: + - salesforce + references: + - https://cwe.mitre.org/data/definitions/284.html + message: >- + Global classes, methods, and variables should be avoided (especially in managed packages) as they can + never be deleted or changed in signature. Always check twice if something needs to be global. + patterns: + - pattern-regex: global [A-Za-z0-9_]{3,} + - pattern-not-regex: //(\s+([a-zA-Z]+\s+)+)[a-zA-Z]+ + - pattern-not-regex: '[*](\s+([a-zA-Z]+\s+)+)[a-zA-Z]+' + paths: + exclude: + - "*Test*" + - "*test*" +- id: apex.lang.best-practice.ncino.tests.useassertclass.use-assert-class + min-version: 1.44.0 + severity: WARNING + languages: + - generic + metadata: + category: best-practice + references: + - https://developer.salesforce.com/docs/atlas.en-us.apexref.meta/apexref/apex_class_System_Assert.htm + technology: + - salesforce + message: >- + Assert methods in the System class have been replaced with the Assert class: + https://developer.salesforce.com/docs/atlas.en-us.apexref.meta/apexref/apex_class_System_Assert.htm + pattern-regex: System\.assert + paths: + include: + - "*.cls" + - "UseAssertClass.cls" +- id: apex.lang.best-practice.ncino.urls.absoluteurls.absolute-urls + min-version: 1.44.0 + severity: WARNING + languages: + - apex + metadata: + category: best-practice + references: + - '' + technology: + - salesforce + message: >- + Using absolute URLs to Salesforce Pages is bug prone. Different sandboxes and production + environments will have different instance names (like "na10", "na15" etc.). Code using + absolute URLs will only work when it runs in the corresponding salesforce instances. It + will break as soon as it is deployed in another one. Thus only relative URLs, i.e. without + the domain and subdomain names, should be used when pointing to a salesforce page. + pattern-regex: (http|https)://.*(salesforce|force|visualforce)\.com\.* + paths: + exclude: + - "*Test*" + - "*test*" +- id: apex.lang.performance.ncino.operationsinloops.avoidnativedmlinloops.avoid-native-dml-in-loops + min-version: 1.44.0 + severity: ERROR + languages: + - generic + metadata: + category: performance + references: + - https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_gov_limits.htm + technology: + - salesforce + message: >- + Avoid DML statements inside loops to avoid hitting the DML governor limit. + Instead, try to batch up the data into a list and invoke your DML once on + that list of data outside the loop. + patterns: + - pattern-either: + - pattern-inside: | + for (...) { + ... + } + - pattern-inside: | + while (...) { + ... + } + - pattern-inside: | + do { + ... + } while (...); + - pattern-either: + - pattern: | + insert $DATA; + - pattern: | + update $DATA; + - pattern: | + upsert $DATA; + - pattern: | + delete $DATA; + - pattern: | + Database.insert($DATA); + - pattern: | + Database.update($DATA); + - pattern: | + Database.upsert($DATA); + - pattern: | + Database.delete($DATA); +- id: apex.lang.performance.ncino.operationsinloops.avoidoperationswithlimitsinloops.avoid-operations-with-limits-in-loops + min-version: 1.44.0 + severity: ERROR + languages: + - generic + metadata: + category: performance + references: + - https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_gov_limits.htm + technology: + - salesforce + message: >- + Database class methods, DML operations, SOQL queries, SOSL queries, + Approval class methods, Email sending, async scheduling or queueing + within loops can cause governor limit exceptions. Instead, try to + batch up the data into a list and invoke the operation once on that + list of data outside the loop. + patterns: + - pattern-either: + - pattern-inside: | + for (...) { + ... + } + - pattern-inside: | + while (...) { + ... + } + - pattern-inside: | + do { + ... + } while (...); + - pattern-either: + - pattern: | + Messaging.sendEmail(...); + - pattern: | + Approval.ProcessSubmitRequest $REQUEST = new Approval.ProcessSubmitRequest(); + - pattern: | + System.enqueueJob(...); + - pattern: | + System.schedule(...); + - pattern: | + System.scheduleBatch(...); +- id: apex.lang.performance.ncino.operationsinloops.avoidsoqlinloops.avoid-soql-in-loops + min-version: 1.44.0 + severity: ERROR + languages: + - generic + metadata: + category: performance + references: + - https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_gov_limits.htm + technology: + - salesforce + message: >- + Database class methods, DML operations, SOQL queries, SOSL queries, + Approval class methods, Email sending, async scheduling or queueing + within loops can cause governor limit exceptions. Instead, try to + batch up the data into a list and invoke the operation once on that + list of data outside the loop. + patterns: + - pattern-either: + - pattern-inside: | + for (...) { + ... + } + - pattern-inside: | + while (...) { + ... + } + - pattern-inside: | + do { + ... + } while (...); + - pattern: | + $OBJECTS = [...SELECT...FROM...]; +- id: apex.lang.performance.ncino.operationsinloops.avoidsoslinloops.avoid-sosl-in-loops + min-version: 1.44.0 + severity: ERROR + languages: + - generic + metadata: + category: performance + references: + - https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_gov_limits.htm + technology: + - salesforce + message: >- + Database class methods, DML operations, SOQL queries, SOSL queries, + Approval class methods, Email sending, async scheduling or queueing + within loops can cause governor limit exceptions. Instead, try to + batch up the data into a list and invoke the operation once on that + list of data outside the loop. + patterns: + - pattern-either: + - pattern-inside: | + for (...) { + ... + } + - pattern-inside: | + while (...) { + ... + } + - pattern-inside: | + do { + ... + } while (...); + - pattern-either: + - pattern: | + $OBJECTS = ... Search.query(...) + - pattern: | + $OBJECTS = ... [FIND...IN ALL FIELDS RETURNING...] +- id: apex.lang.security.ncino.dml.apexcsrfconstructor.apex-csrf-constructor + min-version: 1.44.0 + severity: ERROR + languages: + - apex + metadata: + cwe: + - 'CWE-352: Cross-Site Request Forgery (CSRF)' + owasp: + - A01:2021 - Broken Access Control + cwe2020-top25': true + cwe2021-top25': true + cwe2022-top25': true + impact: HIGH + likelihood: MEDIUM + confidence: HIGH + category: security + subcategory: + - vuln + technology: + - salesforce + references: + - https://cwe.mitre.org/data/definitions/352.html + message: >- + Having DML operations in Apex class constructor or initializers can + have unexpected side effects: By just accessing a page, the DML statements + would be executed and the database would be modified. Just querying the + database is permitted. + patterns: + - pattern-either: + - pattern-inside: public class $CLASSNAME {...} + - pattern-inside: private class $CLASSNAME {...} + - pattern-inside: public $SOME sharing class $CLASSNAME {...} + - pattern-inside: private $SOME sharing class $CLASSNAME {...} + - pattern-either: + - pattern-inside: public $CLASSNAME() {...} + - pattern-inside: private $CLASSNAME() {...} + - pattern-either: + - pattern: | + insert $DATA; + - pattern: | + update $DATA; + - pattern: | + upsert $DATA; + - pattern: | + delete $DATA; + paths: + exclude: + - "*Test*" + - "*test*" +- id: apex.lang.security.ncino.dml.apexcsrfstaticconstructor.apex-csrf-static-constructor + min-version: 1.44.0 + severity: ERROR + languages: + - generic + metadata: + cwe: + - 'CWE-352: Cross-Site Request Forgery (CSRF)' + owasp: + - A01:2021 - Broken Access Control + cwe2020-top25': true + cwe2021-top25': true + cwe2022-top25': true + impact: HIGH + likelihood: MEDIUM + confidence: HIGH + category: security + subcategory: + - vuln + technology: + - salesforce + references: + - https://cwe.mitre.org/data/definitions/352.html + message: >- + Having DML operations in Apex class constructor or initializers can + have unexpected side effects: By just accessing a page, the DML statements + would be executed and the database would be modified. Just querying the + database is permitted. + patterns: + - pattern-inside: static {...} + - pattern-either: + - pattern: | + insert $DATA; + - pattern: | + update $DATA; + - pattern: | + upsert $DATA; + - pattern: | + delete $DATA; + paths: + exclude: + - "*Test*" + - "*test*" +- id: apex.lang.security.ncino.dml.dmlnativestatements.dml-native-statements + min-version: 1.44.0 + severity: WARNING + languages: + - apex + metadata: + cwe: + - 'CWE-863: Incorrect Authorization' + owasp: + - A01:2021 - Broken Access Control + - A04:2021 - Insecure Design + impact: HIGH + likelihood: LOW + confidence: LOW + category: security + subcategory: + - audit + technology: + - salesforce + references: + - https://developer.salesforce.com/docs/atlas.en-us.apexref.meta/apexref/apex_dml_section.htm + - https://cwe.mitre.org/data/definitions/863.html + - https://owasp.org/Top10/A04_2021-Insecure_Design/ + message: >- + Native Salesforce DML operations execute in system context, ignoring the current user's permissions, + field-level security, organization-wide defaults, position in the role hierarchy, and sharing rules. + Be mindful when using native Salesforce DML operations. + patterns: + - pattern-either: + - pattern-regex: '(insert|upsert|update|delete)[\s]' + - pattern-regex: '(insert|upsert|update|delete)[(]' + - pattern-not-regex: '[\/\/].*(insert|upsert|update|delete).*' + - pattern-not-regex: '[\/\/].*(insert|upsert|update|delete)[\n]' + - pattern-not-regex: '.*[=].*(insert|upsert|update|delete).*[,;]' +- id: apex.lang.security.ncino.encryption.badcrypto.bad-crypto + min-version: 1.44.0 + severity: ERROR + languages: + - apex + metadata: + cwe: + - 'CWE-321: Use of Hard-coded Cryptographic Key' + owasp: + - A02:2021 - Cryptographic Failures + impact: HIGH + likelihood: LOW + confidence: LOW + category: security + subcategory: + - audit + technology: + - salesforce + references: + - https://cwe.mitre.org/data/definitions/321.html + message: >- + The rule makes sure you are using randomly generated IVs and keys + for Crypto calls. Hard-coding these values greatly compromises the + security of encrypted data. + pattern-either: + - pattern: Blob $IV = Blob.valueOf('$STRING');...Crypto.encrypt($ONE, $TWO, $IV, $FOUR); + - pattern: Blob $IV = Blob.valueOf('$STRING');...Crypto.decrypt($ONE, $TWO, $IV, $FOUR); + - pattern: Blob $KEY = Blob.valueOf('$STRING');...Crypto.encrypt($ONE, $KEY, $THREE, $FOUR); + - pattern: Blob $KEY = Blob.valueOf('$STRING');...Crypto.decrypt($ONE, $KEY, $THREE, $FOUR); + paths: + exclude: + - "*Test*" + - "*test*" +- id: apex.lang.security.ncino.endpoints.insecurehttprequest.insecure-http-request + min-version: 1.44.0 + severity: ERROR + languages: + - apex + metadata: + cwe: + - 'CWE-319: Cleartext Transmission of Sensitive Information' + impact: MEDIUM + likelihood: LOW + confidence: MEDIUM + category: security + subcategory: + - vuln + technology: + - salesforce + references: + - https://cwe.mitre.org/data/definitions/319.html + message: >- + The software transmits sensitive or security-critical data in cleartext in + a communication channel that can be sniffed by unauthorized actors. + patterns: + - pattern-regex: http[:][/][/] + - pattern-not-regex: //.* + - pattern-not-regex: '[*].*' + paths: + exclude: + - "*Test*" + - "*test*" +- id: apex.lang.security.ncino.endpoints.namedcredentialsconstantmatch.named-credentials-constant-match + min-version: 1.44.0 + mode: taint + severity: ERROR + languages: + - apex + metadata: + cwe: + - 'CWE-540: Inclusion of Sensitive Information in Source Code' + impact: HIGH + likelihood: LOW + confidence: HIGH + category: security + subcategory: + - vuln + technology: + - salesforce + references: + - https://cwe.mitre.org/data/definitions/540.html + message: >- + Named Credentials (and callout endpoints) should be used instead of hard-coding credentials. + 1. Hard-coded credentials are hard to maintain when mixed in with application code. + 2. It is particularly hard to update hard-coded credentials when they are used amongst different classes. + 3. Granting a developer access to the codebase means granting knowledge of credentials, and thus keeping a two-level access is not possible. + 4. Using different credentials for different environments is troublesome and error-prone. + pattern-sources: + - pattern: ...String $X = 'Authorization'; + pattern-sinks: + - patterns: + - pattern: req.setHeader($X, ...); + - focus-metavariable: $X +- id: apex.lang.security.ncino.endpoints.namedcredentialsstringmatch.named-credentials-string-match + min-version: 1.44.0 + severity: ERROR + languages: + - apex + metadata: + cwe: + - 'CWE-540: Inclusion of Sensitive Information in Source Code' + impact: HIGH + likelihood: LOW + confidence: HIGH + category: security + subcategory: + - vuln + technology: + - salesforce + references: + - https://cwe.mitre.org/data/definitions/540.html + message: >- + Named Credentials (and callout endpoints) should be used instead of hard-coding credentials. + 1. Hard-coded credentials are hard to maintain when mixed in with application code. + 2. It is particularly hard to update hard-coded credentials when they are used amongst different classes. + 3. Granting a developer access to the codebase means granting knowledge of credentials, and thus keeping a two-level access is not possible. + 4. Using different credentials for different environments is troublesome and error-prone. + pattern: $REQUEST.setHeader('Authorization', $AUTHSTRING); +- id: apex.lang.security.ncino.injection.apexsoqlinjectionfromunescapedurlparam.soql-injection-unescaped-url-param + min-version: 1.44.0 + mode: taint + severity: ERROR + languages: + - apex + metadata: + category: security + subcategory: + - vuln + technology: + - salesforce + cwe: + - 'CWE-943: Improper Neutralization of Special Elements in Data Query Logic' + owasp: + - A03:2021 - Injection + references: + - https://cwe.mitre.org/data/definitions/943.html + impact: HIGH + likelihood: HIGH + confidence: HIGH + message: >- + If a dynamic query must be used,leverage nFORCE Query Builder. + In other programming languages, the related flaw is known as SQL injection. + Apex doesn't use SQL, but uses its own database query language, SOQL. SOQL is + much simpler and more limited in functionality than SQL. The risks are much + lower for SOQL injection than for SQL injection, but the attacks are nearly + identical to traditional SQL injection. SQL/SOQL injection takes user-supplied + input and uses those values in a dynamic SOQL query. If the input isn't validated, + it can include SOQL commands that effectively modify the SOQL statement and trick + the application into performing unintended commands. + pattern-sources: + - by-side-effect: true + pattern: ApexPage.getCurrentPage().getParameters.get($URLPARAM); + pattern-sanitizers: + - pattern: String.escapeSingleQuotes(...) + pattern-sinks: + - patterns: + - pattern: Database.query($SINK,...); + - focus-metavariable: $SINK +- id: apex.lang.security.ncino.injection.apexsoqlinjectionunescapedparam.soql-injection-unescaped-param + min-version: 1.44.0 + mode: taint + severity: ERROR + languages: + - apex + metadata: + category: security + subcategory: + - vuln + technology: + - salesforce + cwe: + - 'CWE-943: Improper Neutralization of Special Elements in Data Query Logic' + owasp: + - A03:2021 - Injection + references: + - https://cwe.mitre.org/data/definitions/943.html + impact: HIGH + likelihood: HIGH + confidence: HIGH + message: >- + If a dynamic query must be used,leverage nFORCE Query Builder. + In other programming languages, the related flaw is known as SQL injection. + Apex doesn't use SQL, but uses its own database query language, SOQL. SOQL is + much simpler and more limited in functionality than SQL. The risks are much + lower for SOQL injection than for SQL injection, but the attacks are nearly + identical to traditional SQL injection. SQL/SOQL injection takes user-supplied + input and uses those values in a dynamic SOQL query. If the input isn't validated, + it can include SOQL commands that effectively modify the SOQL statement and trick + the application into performing unintended commands. + pattern-sources: + - by-side-effect: true + patterns: + - pattern: $M(...,String $P,...) { ... } + - focus-metavariable: $P + pattern-sanitizers: + - pattern-either: + - pattern: String.escapeSingleQuotes($P) + - pattern: Database.query(<... String.escapeSingleQuotes($P) ...>) + pattern-sinks: + - pattern: Database.query(<... $P ...>) +- id: apex.lang.security.ncino.sharing.specifysharinglevel.specify-sharing-level + min-version: 1.44.0 + severity: WARNING + languages: + - apex + metadata: + cwe: + - 'CWE-284: Improper Access Control' + owasp: + - A04:2021 - Insecure Design + references: + - https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_classes_keywords_sharing.htm + - https://cwe.mitre.org/data/definitions/284.html + - https://owasp.org/Top10/A04_2021-Insecure_Design/ + category: security + subcategory: + - vuln + technology: + - salesforce + impact: MEDIUM + likelihood: MEDIUM + confidence: HIGH + message: >- + Every Apex class should have an explicit sharing mode declared. Use the `with sharing` + or `without sharing` keywords on a class to specify whether sharing rules must be enforced. + Use the `inherited sharing` keyword on an Apex class to run the class in the sharing mode + of the class that called it. + patterns: + - pattern-regex: (private|public|global).*\s(class)\s.*[{] + - pattern-not-regex: (private|public|global).*[with|without|inherited]\s[sharing].*\s(class)\s.*[{] + - pattern-not-regex: (private|public|global).*\s(class)\s.*(extends)\s(Exception).*[{] +- id: apex.lang.security.ncino.system.systemdebug.system-debug + min-version: 1.44.0 + severity: WARNING + languages: + - apex + metadata: + cwe: + - 'CWE-489: Active Debug Code' + - 'CWE-779: Logging of Excessive Data' + category: security + subcategory: + - vuln + technology: + - vuln + references: + - https://cwe.mitre.org/data/definitions/489.html + - https://cwe.mitre.org/data/definitions/779.html + impact: MEDIUM + likelihood: LOW + confidence: HIGH + message: >- + In addition to debug statements potentially logging data excessively, debug statements + also contribute to longer transactions and consume Apex CPU time even when debug logs + are not being captured. + pattern: System.debug(...) + paths: + exclude: + - "*Test*" + - "*test*" +- id: bash.curl.security.curl-eval.curl-eval + severity: WARNING + languages: + - bash + message: Data is being eval'd from a `curl` command. An attacker with control of the server in the `curl` + command could inject malicious code into the `eval`, resulting in a system comrpomise. Avoid eval'ing + untrusted data if you can. If you must do this, consider checking the SHA sum of the content returned + by the server to verify its integrity. + metadata: + owasp: + - A03:2021 - Injection + cwe: + - "CWE-95: Improper Neutralization of Directives in Dynamically Evaluated Code ('Eval Injection')" + category: security + technology: + - bash + - curl + confidence: MEDIUM + references: + - https://owasp.org/Top10/A03_2021-Injection + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + mode: taint + pattern-sources: + - pattern: | + $(curl ...) + - pattern: | + `curl ...` + pattern-sinks: + - pattern: eval ... +- id: bash.curl.security.curl-pipe-bash.curl-pipe-bash + languages: [bash] + severity: WARNING + message: >- + Data is being piped into `bash` from a `curl` command. An attacker with control of the server + in the `curl` command could inject malicious code into the pipe, resulting in a + system compromise. Avoid piping untrusted data into `bash` or any other shell if you can. + If you must do this, consider checking the SHA sum of the content returned by the server to verify + its + integrity. + metadata: + owasp: + - A03:2021 - Injection + cwe: + - "CWE-95: Improper Neutralization of Directives in Dynamically Evaluated Code ('Eval Injection')" + category: security + technology: + - bash + - curl + confidence: LOW + references: + - https://owasp.org/Top10/A03_2021-Injection + subcategory: + - audit + likelihood: LOW + impact: LOW + patterns: + - pattern-either: + - pattern: curl ... | ... bash ... + - pattern: curl ... | ... /bin/bash ... + - pattern: ... bash <(curl ...) + - pattern: ... /bin/bash <(curl ...) + - pattern: ... bash -c "$(curl ...)" + - pattern: ... /bin/bash -c "$(curl ...)" +- id: bash.lang.best-practice.iteration-over-ls-output.iteration-over-ls-output + patterns: + - pattern: | + for $VAR in $LIST; do + ... + done + - pattern: | + $(ls ...) + message: >- + Iterating over ls output is fragile. Use globs, e.g. 'dir/*' instead + of '$(ls dir)'. + metadata: + references: + - https://github.com/koalaman/shellcheck/wiki/SC2045 + category: best-practice + technology: + - bash + severity: WARNING + languages: + - bash +- id: bash.lang.best-practice.useless-cat.useless-cat + pattern-either: + - pattern: | + cat | ... + - patterns: + - pattern: | + cat $ARG | ... + - pattern-not: | + cat ${$SEVERAL_FILES} | ... + - pattern: | + ... | cat + - pattern: | + ... | cat | ... + # TODO: autofix, once we support $...ARGS + message: >- + Useless call to 'cat' in a pipeline. Use '<' and '>' for any command + to read from a file or write to a file. + metadata: + references: + - https://github.com/koalaman/shellcheck/wiki/SC2002 + category: best-practice + technology: + - bash + severity: WARNING + languages: + - bash +- id: bash.lang.correctness.unquoted-expansion.unquoted-variable-expansion-in-command + languages: [bash] + severity: INFO + message: >- + Variable expansions must be double-quoted so as to prevent + being split into multiple pieces according to whitespace or + whichever separator is specified by the IFS variable. + If you really wish to split the variable's contents, + you may use a variable that starts with an underscore e.g. + $_X instead of $X, and semgrep will ignore it. If what you need + is an array, consider using a proper bash array. + metadata: + category: correctness + technology: + - bash + patterns: + - pattern-either: + # This is subtle (and not great): ...${$VAR}... is a concatenation, + # which is interpreted as concatenate(..., expand($VAR), ...) + # and won't match a simple variable expansion. + # This is why we need two patterns below. + - pattern: | + ... ${$VAR} ... + - pattern: | + ... ...${$VAR}... ... + - metavariable-regex: + metavariable: + $VAR + # generally safe: $# $? $$ $! $- + # unsafe: $* $@ $0 $15 $_ $foo $FOO + # unsafe but tolerated: $_foo $_FOO $_42 + regex: "[*@0-9]|[A-Za-z].*" + +- id: bash.lang.correctness.unquoted-expansion.unquoted-command-substitution-in-command + languages: [bash] + severity: INFO + message: >- + The result of command substitution $(...) or `...`, if unquoted, + is split on whitespace or other separators specified by the IFS + variable. You should surround it with double quotes to avoid + splitting the result. + metadata: + category: correctness + technology: + - bash + patterns: + - pattern-either: + - pattern: | + ... $(...) ... + - pattern: | + ... ...$(...)... ... + - pattern-regex: | + .*(\$\([^\(]|`).+([^\)]\)|`).* +- id: bash.lang.security.ifs-tampering.ifs-tampering + languages: [bash] + severity: WARNING + message: >- + The special variable IFS affects how splitting takes place when + expanding unquoted variables. Don't set it globally. + Prefer a dedicated utility such as 'cut' or 'awk' if you need to split + input data. If you must use 'read', set IFS locally using e.g. + 'IFS="," read -a my_array'. + pattern: IFS=... + metadata: + cwe: + - 'CWE-20: Improper Input Validation' + category: security + technology: + - bash + confidence: LOW + owasp: + - A03:2021 - Injection + references: + - https://owasp.org/Top10/A03_2021-Injection + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: LOW +- id: c.lang.correctness.c-string-equality.c-string-equality + patterns: + - pattern: (char *$X) == (char *$Y) + - metavariable-comparison: + metavariable: $X + comparison: $X != 0 + - metavariable-comparison: + metavariable: $Y + comparison: $Y != 0 + message: Using == on char* performs pointer comparison, use strcmp instead + fix: strcmp($X, $Y) == 0 + languages: [c,cpp] + severity: ERROR + metadata: + category: correctness + technology: + - c + - cpp +- id: c.lang.correctness.goto-fail.double_goto + pattern: | + if ($COND) + goto $FAIL; + goto $FAIL; + message: The second goto statement will always be executed. + languages: [c,cpp] + severity: WARNING + metadata: + category: correctness + technology: + - c + - cpp +- id: c.lang.correctness.incorrect-use-ato-fn.incorrect-use-ato-fn + pattern-either: + - pattern: atoi(...) + - pattern: atol(...) + - pattern: atoll(...) + message: >- + Avoid the 'ato*()' family of functions. Their use can lead to undefined + behavior, integer overflows, and lack of appropriate error handling. Instead + prefer the 'strtol*()' family of functions. + metadata: + references: + - https://stackoverflow.com/q/38393162 + - https://stackoverflow.com/q/14176123 + category: correctness + technology: + - c + - cpp + languages: [c,cpp] + severity: WARNING +- id: c.lang.correctness.incorrect-use-sscanf-fn.incorrect-use-sscanf-fn + patterns: + - pattern: sscanf($STR, $FMT, $PTR); + - metavariable-regex: + metavariable: $FMT + regex: '"%(l{0,2}|L)([fegEa]|[dDiouxX])"' + message: >- + Avoid 'sscanf()' for number conversions. Its use can lead to undefined + behavior, slow processing, and integer overflows. Instead prefer the + 'strto*()' family of functions. + metadata: + references: + - https://stackoverflow.com/q/22865622 + - https://stackoverflow.com/q/7021725 + - https://www.mattkeeter.com/blog/2021-03-01-happen/ + category: correctness + technology: + - c + - cpp + languages: [c,cpp] + severity: WARNING +- id: c.lang.security.double-free.double-free + patterns: + - pattern-not: | + free($VAR); + ... + $VAR = NULL; + ... + free($VAR); + - pattern-not: | + free($VAR); + ... + $VAR = malloc(...); + ... + free($VAR); + - pattern-inside: | + free($VAR); + ... + $FREE($VAR); + - metavariable-pattern: + metavariable: $FREE + pattern: free + - focus-metavariable: $FREE + message: >- + Variable '$VAR' was freed twice. This can lead to undefined behavior. + metadata: + cwe: + - 'CWE-415: Double Free' + owasp: + - A03:2021 - Injection + - A01:2017 - Injection + references: + - https://cwe.mitre.org/data/definitions/415.html + - https://owasp.org/www-community/vulnerabilities/Doubly_freeing_memory + category: security + technology: + - c + - cpp + confidence: LOW + subcategory: + - vuln + likelihood: LOW + impact: HIGH + languages: [c,cpp] + severity: ERROR +- id: c.lang.security.function-use-after-free.function-use-after-free + patterns: + - pattern-either: + - pattern: $FUNC(..., <... $VAR ...>, ...) + - pattern: $FUNC(..., <... $VAR->$ACCESSOR ...>, ...) + - pattern: $FUNC(..., <... (*$VAR).$ACCESSOR ...>, ...) + - pattern: $FUNC(..., <... $VAR[$NUM] ...>, ...) + - metavariable-regex: + metavariable: $FUNC + regex: (?!^free$) + - pattern-inside: + free($VAR); + ... + - pattern-not-inside: + free($VAR); + ... + $VAR = NULL; + ... + - pattern-not-inside: + free($VAR); + ... + $VAR = malloc(...); + ... + message: Variable '$VAR' was passed to a function after being freed. This can lead to undefined behavior. + metadata: + cwe: + - "CWE-416: Use After Free" + references: + - https://cwe.mitre.org/data/definitions/416.html + - https://ctf-wiki.github.io/ctf-wiki/pwn/linux/glibc-heap/use_after_free/ + category: security + technology: + - c + - cpp + confidence: LOW + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: LOW + impact: HIGH + languages: + - c + - cpp + severity: WARNING +- id: c.lang.security.info-leak-on-non-formatted-string.info-leak-on-non-formated-string + message: >- + Use %s, %d, %c... to format your variables, otherwise this could leak information. + metadata: + cwe: + - 'CWE-532: Insertion of Sensitive Information into Log File' + references: + - http://nebelwelt.net/files/13PPREW.pdf + category: security + technology: + - c + - cpp + confidence: LOW + owasp: + - A09:2021 - Security Logging and Monitoring Failures + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + languages: [c,cpp] + severity: WARNING + pattern: printf(argv[$NUM]); +- id: c.lang.security.insecure-use-gets-fn.insecure-use-gets-fn + pattern: gets(...) + message: >- + Avoid 'gets()'. This function does not consider buffer boundaries and can lead + to buffer overflows. Use 'fgets()' or 'gets_s()' instead. + metadata: + cwe: + - 'CWE-676: Use of Potentially Dangerous Function' + references: + - https://us-cert.cisa.gov/bsi/articles/knowledge/coding-practices/fgets-and-gets_s + category: security + technology: + - c + - cpp + confidence: MEDIUM + subcategory: + - audit + likelihood: LOW + impact: HIGH + languages: [c,cpp] + severity: ERROR +- id: c.lang.security.insecure-use-memset.insecure-use-memset + pattern: memset($...VARS) + fix: memset_s($...VARS) + message: >- + When handling sensitive information in a buffer, it's important to ensure + that the data is securely erased before the buffer is deleted or reused. + While `memset()` is commonly used for this purpose, it can leave sensitive + information behind due to compiler optimizations or other factors. + To avoid this potential vulnerability, it's recommended to use the + `memset_s()` function instead. `memset_s()` is a standardized function + that securely overwrites the memory with a specified value, making it more + difficult for an attacker to recover any sensitive data that was stored in + the buffer. By using `memset_s()` instead of `memset()`, you can help to + ensure that your application is more secure and less vulnerable to exploits + that rely on residual data in memory. + languages: + - c + - cpp + severity: WARNING + metadata: + cwe: + - 'CWE-14: Compiler Removal of Code to Clear Buffers' + owasp: + - "A04:2021 - Insecure Design" + references: + - https://cwe.mitre.org/data/definitions/14.html + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures/ + category: security + technology: + - c + - cpp + confidence: LOW + subcategory: + - audit + likelihood: LOW + impact: MEDIUM +- id: c.lang.security.insecure-use-printf-fn.insecure-use-printf-fn + message: >- + Avoid using user-controlled format strings passed into 'sprintf', 'printf' and + 'vsprintf'. + These functions put you at risk of buffer overflow vulnerabilities through the + use of format string exploits. + Instead, use 'snprintf' and 'vsnprintf'. + metadata: + cwe: + - 'CWE-134: Use of Externally-Controlled Format String' + references: + - https://doc.castsoftware.com/display/SBX/Never+use+sprintf%28%29+or+vsprintf%28%29+functions + - https://www.cvedetails.com/cwe-details/134/Uncontrolled-Format-String.html + category: security + technology: + - c + - cpp + confidence: LOW + subcategory: + - vuln + likelihood: MEDIUM + impact: HIGH + languages: [c,cpp] + severity: WARNING + patterns: + - pattern-either: + - pattern: | + $FUNC($BUFFER, argv[$NUM], ...); + ... + vsprintf(..., $BUFFER, ...); + - pattern: vsprintf(..., argv[$NUM], ...) + - pattern: | + $FUNC($BUFFER, argv[$NUM], ...); + ... + sprintf(..., $BUFFER, ...); + - pattern: sprintf(...,argv[$NUM],...) + - pattern: | + $FUNC($BUFFER, argv[$NUM], ...); + ... + printf(..., $BUFFER, ...); + - pattern: printf(...,argv[$NUM],...) + - metavariable-comparison: + metavariable: $NUM + comparison: int($NUM) > 0 +- id: c.lang.security.insecure-use-scanf-fn.insecure-use-scanf-fn + pattern: scanf(...) + message: >- + Avoid using 'scanf()'. This function, when used improperly, does not consider + buffer boundaries and can lead to buffer overflows. Use 'fgets()' instead + for reading input. + metadata: + cwe: + - 'CWE-676: Use of Potentially Dangerous Function' + references: + - http://sekrit.de/webdocs/c/beginners-guide-away-from-scanf.html + category: security + technology: + - c + - cpp + confidence: LOW + subcategory: + - audit + likelihood: LOW + impact: HIGH + languages: [c,cpp] + severity: WARNING +- id: c.lang.security.insecure-use-strcat-fn.insecure-use-strcat-fn + pattern-either: + - pattern: strcat(...) + - pattern: strncat(...) + message: >- + Finding triggers whenever there is a strcat or strncat used. + This is an issue because strcat or strncat can lead to buffer overflow vulns. + Fix this by using strcat_s instead. + metadata: + cwe: + - 'CWE-676: Use of Potentially Dangerous Function' + references: + - https://nvd.nist.gov/vuln/detail/CVE-2019-12553 + - https://techblog.mediaservice.net/2020/04/cve-2020-2851-stack-based-buffer-overflow-in-cde-libdtsvc/ + category: security + technology: + - c + - cpp + confidence: LOW + subcategory: + - audit + likelihood: LOW + impact: HIGH + languages: [c,cpp] + severity: WARNING +- id: c.lang.security.insecure-use-string-copy-fn.insecure-use-string-copy-fn + pattern-either: + - pattern: strcpy(...) + - pattern: strncpy(...) + message: >- + Finding triggers whenever there is a strcpy or strncpy used. + This is an issue because strcpy does not affirm the size of the destination array + and strncpy will not automatically NULL-terminate strings. + This can lead to buffer overflows, which can cause program crashes + and potentially let an attacker inject code in the program. + Fix this by using strcpy_s instead (although note that strcpy_s is an + optional part of the C11 standard, and so may not be available). + metadata: + cwe: + - 'CWE-676: Use of Potentially Dangerous Function' + references: + - https://cwe.mitre.org/data/definitions/676 + - https://nvd.nist.gov/vuln/detail/CVE-2019-11365 + category: security + technology: + - c + - cpp + confidence: LOW + subcategory: + - audit + likelihood: LOW + impact: HIGH + languages: [c,cpp] + severity: WARNING +- id: c.lang.security.insecure-use-strtok-fn.insecure-use-strtok-fn + pattern: strtok(...) + message: >- + Avoid using 'strtok()'. This function directly modifies the first argument buffer, + permanently erasing the + delimiter character. Use 'strtok_r()' instead. + metadata: + cwe: + - 'CWE-676: Use of Potentially Dangerous Function' + references: + - https://wiki.sei.cmu.edu/confluence/display/c/STR06-C.+Do+not+assume+that+strtok%28%29+leaves+the+parse+string+unchanged + - https://man7.org/linux/man-pages/man3/strtok.3.html#BUGS + - https://stackoverflow.com/a/40335556 + category: security + technology: + - c + - cpp + confidence: LOW + subcategory: + - audit + likelihood: LOW + impact: HIGH + languages: [c,cpp] + severity: WARNING +- id: c.lang.security.random-fd-exhaustion.random-fd-exhaustion + pattern-either: + - patterns: + - pattern: | + $FD = open("/dev/urandom", ...); + ... + read($FD, ...); + - pattern-not: | + $FD = open("/dev/urandom", ...); + ... + $BYTES_READ = read($FD, ...); + - patterns: + - pattern: | + $FD = open("/dev/random", ...); + ... + read($FD, ...); + - pattern-not: | + $FD = open("/dev/random", ...); + ... + $BYTES_READ = read($FD, ...); + message: >- + Call to 'read()' without error checking is susceptible to file descriptor + exhaustion. Consider using the 'getrandom()' function. + metadata: + cwe: + - 'CWE-774: Allocation of File Descriptors or Handles Without Limits or Throttling' + references: + - https://lwn.net/Articles/606141/ + category: security + technology: + - c + - cpp + confidence: MEDIUM + subcategory: + - audit + likelihood: LOW + impact: HIGH + languages: [c,cpp] + severity: WARNING +- id: c.lang.security.use-after-free.use-after-free + patterns: + - pattern-either: + - pattern: $VAR->$ACCESSOR + - pattern: (*$VAR).$ACCESSOR + - pattern: $VAR[$NUM] + - pattern-inside: + free($VAR); + ... + - pattern-not-inside: + $VAR = NULL; + ... + - pattern-not-inside: + free($VAR); + ... + $VAR = malloc(...); + ... + message: >- + Variable '$VAR' was used after being freed. This can lead to undefined behavior. + metadata: + cwe: + - "CWE-416: Use After Free" + references: + - https://cwe.mitre.org/data/definitions/416.html + - https://ctf-wiki.github.io/ctf-wiki/pwn/linux/glibc-heap/use_after_free/ + category: security + technology: + - c + - cpp + confidence: LOW + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: LOW + impact: HIGH + languages: + - c + - cpp + severity: WARNING +- id: clojure.lang.security.command-injection-shell-call.command-injection-shell-call + metadata: + author: Gabriel Marquet + category: security + confidence: LOW + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + cwe: + - "CWE-78: Improper Neutralization of Special Elements used in an OS Command + ('OS Command Injection')" + likelihood: MEDIUM + impact: HIGH + subcategory: + - audit + technology: + - clojure + references: + - https://clojuredocs.org/clojure.java.shell/sh + patterns: + - pattern-either: + - pattern-inside: "(ns ...\n...\n(:require \n... \n[clojure.java.shell ... + [sh]]\n...\n))\n...\n" + - pattern-inside: "(ns ...\n...\n(:use \n... \n[clojure.java.shell ... [sh]]\n...\n))\n...\n" + - pattern-either: + - patterns: + - pattern: (sh $BASH ...) + - metavariable-regex: + metavariable: $BASH + regex: (.*)(sh|bash|ksh|csh|tcsh|zsh) + - patterns: + - pattern: (sh $ARG ...) + - pattern-not: (sh "..." ...) + languages: + - clojure + severity: ERROR + message: >- + A call to clojure.java.shell has been found, this could lead to an RCE if the + inputs are user-controllable. Please ensure their origin is validated and sanitized. +- id: clojure.lang.security.documentbuilderfactory-xxe.documentbuilderfactory-xxe + languages: + - clojure + severity: ERROR + metadata: + cwe: + - 'CWE-611: Improper Restriction of XML External Entity Reference' + owasp: + - A04:2017 - XML External Entities (XXE) + - A05:2021 - Security Misconfiguration + asvs: + section: V5 Validation, Sanitization and Encoding + control_id: 5.5.2 Insecue XML Deserialization + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x13-V5-Validation-Sanitization-Encoding.md#v55-deserialization-prevention + version: '4' + references: + - https://semgrep.dev/blog/2022/xml-security-in-java + - https://semgrep.dev/docs/cheat-sheets/java-xxe/ + - https://xerces.apache.org/xerces2-j/features.html + source-rule-url: https://github.com/clj-holmes/clj-holmes-rules/blob/main/security/xxe-clojure-xml/xxe-clojure-xml.yml + category: security + technology: + - clojure + - xml + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: LOW + impact: HIGH + confidence: HIGH + message: >- + DOCTYPE declarations are enabled for javax.xml.parsers.SAXParserFactory. + Without prohibiting external entity declarations, this is vulnerable to XML external entity attacks. + Disable this by setting the feature "http://apache.org/xml/features/disallow-doctype-decl" to true. + Alternatively, allow DOCTYPE declarations and only prohibit external entities declarations. + This can be done by setting the features "http://xml.org/sax/features/external-general-entities" and + "http://xml.org/sax/features/external-parameter-entities" to false. + patterns: + - pattern-inside: | + (ns ... (:require [clojure.xml :as ...])) + ... + - pattern-either: + - pattern-inside: | + (def ... ... ( ... )) + - pattern-inside: | + (defn ... ... ( ... )) + - pattern-either: + - pattern: (clojure.xml/parse $INPUT) + - patterns: + - pattern-inside: | + (doto (javax.xml.parsers.SAXParserFactory/newInstance) ...) + - pattern: (.setFeature "http://apache.org/xml/features/disallow-doctype-decl" false) + - pattern-not-inside: | + (doto (javax.xml.parsers.SAXParserFactory/newInstance) + ... + (.setFeature "http://xml.org/sax/features/external-general-entities" false) + ... + (.setFeature "http://xml.org/sax/features/external-parameter-entities" false) + ...) + - pattern-not-inside: | + (doto (javax.xml.parsers.SAXParserFactory/newInstance) + ... + (.setFeature "http://xml.org/sax/features/external-parameter-entities" false) + ... + (.setFeature "http://xml.org/sax/features/external-general-entities" false) + ...) +- id: clojure.lang.security.use-of-md5.use-of-md5 + languages: + - clojure + severity: WARNING + message: >- + MD5 hash algorithm detected. This is not collision resistant and leads to + easily-cracked password hashes. Replace with current recommended hashing + algorithms. + metadata: + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Cryptographic_Storage_Cheat_Sheet.html + - https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html + technology: + - clojure + source-rule-url: https://github.com/clj-holmes/clj-holmes-rules/blob/main/security/weak-hash-function-md5.yml + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + cwe: + - "CWE-328: Use of Weak Hash" + author: Gabriel Marquet + category: security + subcategory: + - vuln + confidence: HIGH + likelihood: MEDIUM + impact: HIGH + pattern-either: + - pattern: (MessageDigest/getInstance "MD5") + - pattern: (MessageDigest/getInstance MessageDigestAlgorithms/MD5) + - pattern: (MessageDigest/getInstance org.apache.commons.codec.digest.MessageDigestAlgorithms/MD5) + - pattern: (java.security.MessageDigest/getInstance "MD5") + - pattern: (java.security.MessageDigest/getInstance MessageDigestAlgorithms/MD5) + - pattern: (java.security.MessageDigest/getInstance org.apache.commons.codec.digest.MessageDigestAlgorithms/MD5) +- id: clojure.lang.security.use-of-sha1.use-of-sha1 + languages: + - clojure + severity: WARNING + message: >- + Detected SHA1 hash algorithm which is considered insecure. SHA1 is not + collision resistant and is therefore not suitable as a cryptographic + signature. Instead, use PBKDF2 for password hashing + or SHA256 or SHA512 for other hash function applications. + metadata: + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Cryptographic_Storage_Cheat_Sheet.html + - https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html + technology: + - clojure + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + cwe: + - "CWE-327: Use of a Broken or Risky Cryptographic Algorithm" + - "CWE-328: Use of Weak Hash" + category: security + subcategory: + - vuln + confidence: HIGH + likelihood: MEDIUM + impact: HIGH + patterns: + - pattern-either: + - pattern: (MessageDigest/getInstance $ALGO) + - pattern: (java.security.MessageDigest/getInstance $ALGO) + - metavariable-regex: + metavariable: $ALGO + regex: (((org\.apache\.commons\.codec\.digest\.)?MessageDigestAlgorithms/)?"?(SHA-1|SHA1)"?) +- id: clojure.security.clojure-read-string.read-string-unsafe.read-string-unsafe + metadata: + author: Gabriel Marquet + category: security + confidence: LOW + references: + - http://www.learningclojure.com/2013/02/clojures-reader-is-unsafe.html#post-body-2898830171141471587 + - https://ericnormand.me/article/clojure-web-security + - https://github.com/jafingerhut/jafingerhut.github.com/blob/master/clojure-info/using-edn-safely.md#vulnerabilities-in-clojurecores-read-and-read-string + source-rule-url: https://github.com/clj-holmes/clj-holmes-rules/tree/main/security/clojure-read-string + owasp: + - A08:2017 - Insecure Deserialization + - A08:2021 - Software and Data Integrity Failures + cwe: + - 'CWE-502: Deserialization of Untrusted Data' + likelihood: MEDIUM + impact: HIGH + subcategory: + - audit + cwe2022-top25: true + cwe2021-top25: true + cwe2020-top25: true + technology: + - clojure + patterns: + - pattern-not-inside: | + (ns ... + (... :exclude [read read-string])) + ... + (defn $VAR [$X]...) + - pattern-inside: | + (defn $VAR [$X]...) + - pattern: | + (read-string $X) + message: >- + The default core Clojure read-string method is dangerous and can lead to + deserialization vulnerabilities. Use the edn/read-string instead. + languages: + - clojure + severity: ERROR +- id: csharp.dotnet.security.audit.ldap-injection.ldap-injection + message: LDAP queries are constructed dynamically on user-controlled input. This vulnerability in code + could lead to an arbitrary LDAP query execution. + severity: ERROR + metadata: + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + category: security + cwe: + - "CWE-90: Improper Neutralization of Special Elements used in an LDAP Query ('LDAP Injection')" + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + references: + - https://owasp.org/Top10/A03_2021-Injection/ + - https://cwe.mitre.org/data/definitions/90 + - https://cheatsheetseries.owasp.org/cheatsheets/LDAP_Injection_Prevention_Cheat_Sheet.html#safe-c-sharp-net-tba-example + subcategory: + - vuln + technology: + - .net + languages: + - csharp + mode: taint + options: + taint_unify_mvars: true + pattern-sources: + - patterns: + - focus-metavariable: $INPUT + - pattern-inside: $T $M($INPUT,...) {...} + pattern-sinks: + - patterns: + - pattern-either: + - pattern: $S.Filter = ... + $INPUT + ... + - pattern: $S.Filter = String.Format(...,$INPUT) + - pattern: $S.Filter = String.Concat(...,$INPUT) + pattern-sanitizers: + - pattern-either: + - pattern: Regex.Replace($INPUT, ...) + - pattern: $ENCODER.LdapFilterEncode($INPUT) + - pattern: $ENCODER.LdapDistinguishedNameEncode($INPUT) +- id: csharp.dotnet.security.audit.mass-assignment.mass-assignment + message: Mass assignment or Autobinding vulnerability in code allows an attacker to execute over-posting + attacks, which could create a new parameter in the binding request and manipulate the underlying object + in the application. + severity: WARNING + metadata: + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + category: security + cwe: + - 'CWE-915: Improperly Controlled Modification of Dynamically-Determined Object Attributes' + owasp: + - A08:2021 - Software and Data Integrity Failures + references: + - https://cwe.mitre.org/data/definitions/915.html + - https://github.com/OWASP/API-Security/blob/master/2019/en/src/0xa6-mass-assignment.md + subcategory: + - vuln + technology: + - .net + languages: + - csharp + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - pattern: | + public IActionResult $METHOD(..., $TYPE $ARG, ...){ + ... + } + - pattern: | + public ActionResult $METHOD(..., $TYPE $ARG, ...){ + ... + } + - pattern-inside: | + using Microsoft.AspNetCore.Mvc; + ... + - pattern-not: | + public IActionResult $METHOD(..., [Bind(...)] $TYPE $ARG, ...){ + ... + } + - pattern-not: | + public ActionResult $METHOD(..., [Bind(...)] $TYPE $ARG, ...){ + ... + } + - focus-metavariable: $ARG + pattern-sinks: + - pattern: View(...) +- id: csharp.dotnet.security.audit.misconfigured-lockout-option.misconfigured-lockout-option + message: >- + A misconfigured lockout mechanism allows an attacker to execute brute-force + attacks. Account lockout must be correctly configured and enabled to prevent these + attacks. + severity: WARNING + metadata: + likelihood: LOW + impact: HIGH + confidence: LOW + category: security + cwe: + - 'CWE-307: Improper Restriction of Excessive Authentication Attempts' + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures + - https://cwe.mitre.org/data/definitions/307.html + subcategory: + - audit + technology: + - dotnet + languages: + - csharp + patterns: + - pattern-either: + - pattern: | + $SIGNIN.PasswordSignInAsync(...,lockoutOnFailure: false,...); + - pattern: | + $SIGNIN.CheckPasswordSignInAsync(...,lockoutOnFailure: false,...); + - pattern-inside: | + public async $TYPE $METHOD(...) { + ... + } +- id: csharp.dotnet.security.audit.missing-or-broken-authorization.missing-or-broken-authorization + message: >- + Anonymous access shouldn't be allowed unless explicit by design. Access + control checks are missing and potentially can be bypassed. This finding violates + the principle of least privilege or deny by default, where access should only + be permitted for a specific set of roles or conforms to a custom policy or users. + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: MEDIUM + category: security + cwe: + - 'CWE-862: Missing Authorization' + cwe2021-top25: true + cwe2022-top25: true + cwe2023-top25: true + owasp: + - A01:2021 - Broken Access Control + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + - https://cwe.mitre.org/data/definitions/862.html + - https://docs.microsoft.com/en-us/aspnet/core/security/authorization/simple?view=aspnetcore-7.0 + subcategory: + - vuln + technology: + - .net + - mvc + languages: + - csharp + patterns: + - pattern: | + public class $CLASS : Controller { + ... + } + - pattern-inside: | + using Microsoft.AspNetCore.Mvc; + ... + - pattern-not: | + [AllowAnonymous] + public class $CLASS : Controller { + ... + } + - pattern-not: | + [Authorize] + public class $CLASS : Controller { + ... + } + - pattern-not: | + [Authorize(Roles = ...)] + public class $CLASS : Controller { + ... + } + - pattern-not: | + [Authorize(Policy = ...)] + public class $CLASS : Controller { + ... + } +- id: csharp.dotnet.security.audit.open-directory-listing.open-directory-listing + message: >- + An open directory listing is potentially exposed, potentially revealing + sensitive information to attackers. + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: MEDIUM + category: security + cwe: + - 'CWE-548: Exposure of Information Through Directory Listing' + owasp: + - A06:2017 - Security Misconfiguration + - A01:2021 - Broken Access Control + references: + - https://cwe.mitre.org/data/definitions/548.html + - https://owasp.org/Top10/A05_2021-Security_Misconfiguration/ + - https://docs.microsoft.com/en-us/aspnet/core/fundamentals/static-files?view=aspnetcore-7.0#directory-browsing + subcategory: + - vuln + technology: + - .net + - mvc + languages: + - csharp + patterns: + - pattern-either: + - pattern: (IApplicationBuilder $APP).UseDirectoryBrowser(...); + - pattern: $BUILDER.Services.AddDirectoryBrowser(...); + - pattern-inside: | + public void Configure(...) { + ... + } +- id: csharp.dotnet.security.audit.razor-use-of-htmlstring.razor-use-of-htmlstring + message: ASP.NET Core MVC provides an HtmlString class which isn't automatically encoded upon output. + This should never be used in combination with untrusted input as this will expose an XSS vulnerability. + severity: WARNING + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - 'CWE-116: Improper Encoding or Escaping of Output' + owasp: + - A03:2021 - Injection + references: + - https://cwe.mitre.org/data/definitions/116.html + - https://owasp.org/Top10/A03_2021-Injection/ + - https://docs.microsoft.com/en-us/aspnet/core/security/cross-site-scripting?view=aspnetcore-6.0#html-encoding-using-razor + subcategory: + - audit + technology: + - .net + languages: + - generic + paths: + include: + - '*.cshtml' + patterns: + - pattern-either: + - pattern: new ...HtmlString(...) + - pattern: '@(new ...HtmlString(...))' + - pattern-not-inside: '@(new ...HtmlString(...HtmlEncode(...)))' + - pattern-not-inside: '@(new ...HtmlString(...Encode(...)))' + - pattern-not-inside: new ...HtmlString(...HtmlEncode(...)) + - pattern-not-inside: new ...HtmlString(...Encode(...)) +- id: csharp.dotnet.security.audit.xpath-injection.xpath-injection + message: XPath queries are constructed dynamically on user-controlled input. This vulnerability in code + could lead to an XPath Injection exploitation. + severity: ERROR + metadata: + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + category: security + cwe: + - "CWE-643: Improper Neutralization of Data within XPath Expressions ('XPath Injection')" + owasp: + - A03:2021 - Injection + references: + - https://owasp.org/Top10/A03_2021-Injection/ + - https://cwe.mitre.org/data/definitions/643.html + subcategory: + - vuln + technology: + - .net + languages: + - csharp + mode: taint + pattern-sources: + - pattern-either: + - pattern: $T $M($INPUT,...) {...} + - pattern: "$T $M(...) {\n ...\n string $INPUT;\n}\n" + pattern-sinks: + - pattern-either: + - pattern: XPathExpression $EXPR = $NAV.Compile("..." + $INPUT + "..."); + - pattern: var $EXPR = $NAV.Compile("..." + $INPUT + "..."); + - pattern: XPathNodeIterator $NODE = $NAV.Select("..." + $INPUT + "..."); + - pattern: var $NODE = $NAV.Select("..." + $INPUT + "..."); + - pattern: Object $OBJ = $NAV.Evaluate("..." + $INPUT + "..."); + - pattern: var $OBJ = $NAV.Evaluate("..." + $INPUT + "..."); +- id: csharp.dotnet.security.mvc-missing-antiforgery.mvc-missing-antiforgery + message: $METHOD is a state-changing MVC method that does not validate the antiforgery token or do strict + content-type checking. State-changing controller methods should either enforce antiforgery tokens + or do strict content-type checking to prevent simple HTTP request types from bypassing CORS preflight + controls. + severity: WARNING + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - 'CWE-352: Cross-Site Request Forgery (CSRF)' + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A01:2021 - Broken Access Control + references: + - https://cheatsheetseries.owasp.org/cheatsheets/DotNet_Security_Cheat_Sheet.html#cross-site-request-forgery + - https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#simple_requests + subcategory: + - audit + technology: + - .net + - mvc + languages: + - csharp + patterns: + - pattern: | + [$HTTPMETHOD] + public IActionResult $METHOD(...){ + ... + } + - pattern-inside: | + using Microsoft.AspNetCore.Mvc; + ... + - pattern-not: | + [ValidateAntiForgeryToken] + public IActionResult $METHOD(...){ + ... + } + - pattern-not: | + [Consumes(...)] + public IActionResult $METHOD(...){ + ... + } + - metavariable-regex: + metavariable: $HTTPMETHOD + regex: Http(Post|Put|Delete|Patch) +- id: csharp.dotnet.security.net-webconfig-debug.net-webconfig-debug + message: >- + ASP.NET applications built with `debug` set to true in production may leak debug information to attackers. + Debug mode also affects performance and reliability. + Set `debug` to `false` or remove it from `` + severity: WARNING + metadata: + likelihood: LOW + impact: LOW + confidence: LOW + category: security + cwe: + - 'CWE-11: ASP.NET Misconfiguration: Creating Debug Binary' + owasp: + - A05:2021 - Security Misconfiguration + references: + - https://web.archive.org/web/20190919105353/https://blogs.msdn.microsoft.com/prashant_upadhyay/2011/07/14/why-debugfalse-in-asp-net-applications-in-production-environment/ + - https://msdn.microsoft.com/en-us/library/e8z01xdh.aspx + subcategory: + - audit + technology: + - .net + languages: [generic] + paths: + include: + - '*web.config*' + patterns: + - pattern: | + + - pattern-inside: | + + ... + +- id: csharp.dotnet.security.net-webconfig-trace-enabled.net-webconfig-trace-enabled + message: >- + OWASP guidance recommends disabling tracing for production applications to prevent accidental leakage + of sensitive application information. + severity: WARNING + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - 'CWE-1323: Improper Management of Sensitive Trace Data' + owasp: 'A05:2021 - Security Misconfiguration' + references: + - https://cheatsheetseries.owasp.org/cheatsheets/DotNet_Security_Cheat_Sheet.html#asp-net-web-forms-guidance + - https://msdn.microsoft.com/en-us/library/e8z01xdh.aspx + subcategory: + - audit + technology: + - .net + languages: [generic] + paths: + include: + - '*web.config*' + patterns: + - pattern: | + + - pattern-inside: | + + ... + +- id: csharp.dotnet.security.razor-template-injection.razor-template-injection + message: User-controllable string passed to Razor.Parse. This leads directly to code execution in the + context of the process. + severity: WARNING + metadata: + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + category: security + cwe: + - "CWE-94: Improper Control of Generation of Code ('Code Injection')" + cwe2022-top25: true + owasp: + - A03:2021 - Injection + references: + - https://clement.notin.org/blog/2020/04/15/Server-Side-Template-Injection-(SSTI)-in-ASP.NET-Razor/ + subcategory: + - vuln + technology: + - .net + - razor + - asp + languages: + - csharp + mode: taint + pattern-sources: + - patterns: + - focus-metavariable: $ARG + - pattern-inside: | + public ActionResult $METHOD(..., string $ARG,...){...} + pattern-sinks: + - pattern: | + Razor.Parse(...) + pattern-sanitizers: + - not_conflicting: true + pattern: $F(...) +- id: csharp.dotnet.security.use_deprecated_cipher_algorithm.use_deprecated_cipher_algorithm + message: Usage of deprecated cipher algorithm detected. Use Aes or ChaCha20Poly1305 instead. + severity: ERROR + metadata: + likelihood: HIGH + impact: MEDIUM + confidence: MEDIUM + category: security + cwe: + - 'CWE-327: Use of a Broken or Risky Cryptographic Algorithm' + owasp: + - A02:2021 - Cryptographic Failures + references: + - https://learn.microsoft.com/en-gb/dotnet/api/system.security.cryptography.des?view=net-6.0#remarks + - https://learn.microsoft.com/en-gb/dotnet/api/system.security.cryptography.rc2?view=net-6.0#remarks + - https://learn.microsoft.com/en-gb/dotnet/api/system.security.cryptography.aes?view=net-6.0 + - https://learn.microsoft.com/en-gb/dotnet/api/system.security.cryptography.chacha20poly1305?view=net-6.0 + subcategory: + - vuln + technology: + - .net + languages: + - csharp + patterns: + - pattern: $KEYTYPE.Create(...); + - metavariable-pattern: + metavariable: $KEYTYPE + pattern-either: + - pattern: DES + - pattern: RC2 +- id: csharp.dotnet.security.use_ecb_mode.use_ecb_mode + message: Usage of the insecure ECB mode detected. You should use an authenticated encryption mode instead, + which is implemented by the classes AesGcm or ChaCha20Poly1305. + severity: WARNING + metadata: + likelihood: HIGH + impact: MEDIUM + confidence: HIGH + category: security + cwe: + - 'CWE-327: Use of a Broken or Risky Cryptographic Algorithm' + owasp: + - A02:2021 - Cryptographic Failures + references: + - https://learn.microsoft.com/en-gb/dotnet/api/system.security.cryptography.chacha20poly1305?view=net-6.0 + - https://learn.microsoft.com/en-gb/dotnet/api/system.security.cryptography.aesgcm?view=net-6.0 + - https://learn.microsoft.com/en-gb/dotnet/api/system.security.cryptography.ciphermode?view=net-6.0 + - https://cheatsheetseries.owasp.org/cheatsheets/Cryptographic_Storage_Cheat_Sheet.html#cipher-modes + subcategory: + - vuln + technology: + - .net + languages: + - csharp + patterns: + - pattern-either: + - pattern: ($KEYTYPE $KEY).EncryptEcb(...); + - pattern: ($KEYTYPE $KEY).DecryptEcb(...); + - pattern: ($KEYTYPE $KEY).Mode = CipherMode.ECB; + - metavariable-pattern: + metavariable: $KEYTYPE + pattern-either: + - pattern: SymmetricAlgorithm + - pattern: Aes + - pattern: Rijndael + - pattern: DES + - pattern: TripleDES + - pattern: RC2 +- id: csharp.dotnet.security.use_weak_rng_for_keygeneration.use_weak_rng_for_keygeneration + message: You are using an insecure random number generator (RNG) to create a cryptographic key. System.Random + must never be used for cryptographic purposes. Use System.Security.Cryptography.RandomNumberGenerator + instead. + severity: ERROR + metadata: + likelihood: HIGH + impact: MEDIUM + confidence: HIGH + category: security + cwe: + - 'CWE-338: Use of Cryptographically Weak Pseudo-Random Number Generator (PRNG)' + owasp: + - A02:2021 - Cryptographic Failures + references: + - https://learn.microsoft.com/en-us/dotnet/api/system.random?view=net-6.0#remarks + - https://learn.microsoft.com/en-us/dotnet/api/system.security.cryptography.randomnumbergenerator?view=net-6.0 + - https://learn.microsoft.com/en-us/dotnet/api/system.security.cryptography.aesgcm?view=net-6.0#constructors + - https://learn.microsoft.com/en-us/dotnet/api/system.security.cryptography.symmetricalgorithm.key?view=net-6.0#system-security-cryptography-symmetricalgorithm-key + subcategory: + - vuln + technology: + - .net + languages: + - csharp + mode: taint + pattern-sources: + - patterns: + - pattern-inside: (System.Random $RNG).NextBytes($KEY); ... + - pattern: $KEY + pattern-sinks: + - pattern-either: + - patterns: + - pattern: ($KEYTYPE $CIPHER).Key = $SINK; + - focus-metavariable: $SINK + - metavariable-pattern: + metavariable: $KEYTYPE + pattern-either: + - pattern: SymmetricAlgorithm + - pattern: Aes + - pattern: Rijndael + - pattern: DES + - pattern: TripleDES + - pattern: RC2 + - pattern: new AesGcm(...) + - pattern: new AesCcm(...) + - pattern: new ChaCha20Poly1305(...) +- id: csharp.dotnet.security.use_weak_rsa_encryption_padding.use_weak_rsa_encryption_padding + message: You are using the outdated PKCS#1 v1.5 encryption padding for your RSA key. Use the OAEP padding + instead. + severity: WARNING + metadata: + likelihood: HIGH + impact: MEDIUM + confidence: MEDIUM + category: security + cwe: + - 'CWE-780: Use of RSA Algorithm without OAEP' + owasp: + - A02:2021 - Cryptographic Failures + references: + - https://learn.microsoft.com/en-gb/dotnet/api/system.security.cryptography.rsapkcs1keyexchangeformatter + - https://learn.microsoft.com/en-gb/dotnet/api/system.security.cryptography.rsaoaepkeyexchangeformatter + - https://learn.microsoft.com/en-gb/dotnet/api/system.security.cryptography.rsapkcs1keyexchangedeformatter + - https://learn.microsoft.com/en-gb/dotnet/api/system.security.cryptography.rsaoaepkeyexchangedeformatter + subcategory: + - vuln + technology: + - .net + languages: + - csharp + pattern-either: + - pattern: (RSAPKCS1KeyExchangeFormatter $FORMATER).CreateKeyExchange(...); + - pattern: (RSAPKCS1KeyExchangeDeformatter $DEFORMATER).DecryptKeyExchange(...); +- id: csharp.dotnet.security.web-config-insecure-cookie-settings.web-config-insecure-cookie-settings + message: Cookie Secure flag is explicitly disabled. You should enforce this value to avoid accidentally + presenting sensitive cookie values over plaintext HTTP connections. + severity: WARNING + metadata: + likelihood: LOW + impact: LOW + confidence: LOW + category: security + cwe: + - "CWE-614: Sensitive Cookie in HTTPS Session Without 'Secure' Attribute" + owasp: + - A05:2021 - Security Misconfiguration + references: + - https://docs.microsoft.com/en-us/aspnet/web-api/overview/advanced/http-cookies + - https://docs.microsoft.com/en-us/dotnet/api/system.web.security.formsauthentication.requiressl?redirectedfrom=MSDN&view=netframework-4.8#System_Web_Security_FormsAuthentication_RequireSSL + - https://docs.microsoft.com/en-us/dotnet/api/system.web.security.roles.cookierequiressl?redirectedfrom=MSDN&view=netframework-4.8#System_Web_Security_Roles_CookieRequireSSL + subcategory: + - audit + technology: + - .net + - asp + - webforms + languages: + - generic + paths: + include: + - '*web.config' + patterns: + - pattern-either: + - pattern: | + requireSSL="false" + - pattern: | + cookieRequireSSL="false" + - pattern-either: + - pattern-inside: | + + - pattern-inside: | + + - pattern-inside: | + +- id: csharp.lang.best-practice.structured-logging.structured-logging + patterns: + - pattern-either: + # Serilog + - pattern: $LOG.Debug($"...") + - pattern: $LOG.Error($"...") + - pattern: $LOG.Fatal($"...") + - pattern: $LOG.Information($"...") + - pattern: $LOG.Verbose($"...") + - pattern: $LOG.Warning($"...") + - pattern: $LOG.LogCritical($"...") + - pattern: $LOG.LogDebug($"...") + - pattern: $LOG.LogError($"...") + - pattern: $LOG.LogInformation($"...") + - pattern: $LOG.LogTrace($"...") + - pattern: $LOG.LogWarning($"...") + - pattern: $LOG.Info($"...") + - pattern: $LOG.Trace($"...") + - pattern: $LOG.Warn($"...") + - metavariable-regex: + metavariable: $LOG + regex: .*(log|LOG|Log) + message: >- + String interpolation in log message obscures the distinction between + variables and the log message. Use structured logging instead, where the + variables are passed as additional arguments and the interpolation is performed + by the logging library. This reduces the possibility of log injection and makes + it easier to search through logs. + languages: [csharp] + severity: INFO + metadata: + cwe: + - 'CWE-117: Improper Output Neutralization for Logs' + owasp: + - A09:2021 - Security Logging and Monitoring Failures + technology: + - .net + - serilog + - nlog + confidence: LOW + references: + - https://github.com/NLog/NLog/wiki/How-to-use-structured-logging + - https://softwareengineering.stackexchange.com/questions/312197/benefits-of-structured-logging-vs-basic-logging + category: best-practice + subcategory: + - audit + likelihood: LOW + impact: LOW +- id: csharp.lang.correctness.double.double-epsilon-equality.correctness-double-epsilon-equality + patterns: + - pattern: | + $V1 - $V2 + - pattern-either: + - pattern-inside: | + ... <= Double.Epsilon + - pattern-inside: | + Double.Epsilon <= ... + - pattern-not-inside: | + double $V1 = 0; + ... + - pattern-not-inside: | + double $V2 = 0; + ... + - pattern-not-inside: | + $V1 = 0; + ... + - pattern-not-inside: | + $V2 = 0; + ... + message: Double.Epsilon is defined by .NET as the smallest value that can be added to or subtracted from a zero-value Double. It is unsuitable for equality comparisons of non-zero Double values. Furthermore, the value of Double.Epsilon is framework and processor architecture dependent. Wherever possible, developers should prefer the framework Equals() method over custom equality implementations. + languages: [csharp] + severity: WARNING + metadata: + references: + - https://docs.microsoft.com/en-us/dotnet/api/system.double?view=net-6.0#testing-for-equality + - https://docs.microsoft.com/en-us/dotnet/api/system.double.epsilon?view=net-6.0#platform-notes + category: correctness + technology: + - .net + confidence: MEDIUM + +- id: csharp.lang.correctness.regioninfo.regioninfo-interop.correctness-regioninfo-interop + patterns: + - pattern-either: + - pattern: | + $WRITER.Write($RI); + - pattern: | + $WRITER.WriteAsync($RI); + - pattern: | + $WRITER.WriteLine($RI); + - pattern: | + $WRITER.WriteLineAsync($RI); + - pattern-inside: | + RegionInfo $RI = new RegionInfo($REGION); + ... + using($PIPESTREAM $P = ...){ + ... + } + - metavariable-regex: + metavariable: $REGION + regex: ^"\w{2}"$ + - metavariable-regex: + metavariable: $PIPESTREAM + regex: (Anonymous|Named)Pipe(Server|Client)Stream + message: >- + Potential inter-process write of RegionInfo $RI via $PIPESTREAM $P that was instantiated with a two-character culture code $REGION. + Per .NET documentation, if you want to persist a RegionInfo object or communicate it between processes, you should instantiate it by using a full culture name rather than a two-letter ISO region code. + languages: + - csharp + severity: WARNING + metadata: + references: + - https://docs.microsoft.com/en-us/dotnet/api/system.globalization.regioninfo.twoletterisoregionname?view=net-6.0#remarks + technology: + - .net + category: correctness + confidence: MEDIUM +- id: csharp.lang.correctness.sslcertificatetrust.sslcertificatetrust-handshake-no-trust.correctness-sslcertificatetrust-handshake-no-trust + patterns: + - pattern-either: + - pattern: SslCertificateTrust.$METHOD($COLLECTION,sendTrustInHandshake=true) + - pattern: SslCertificateTrust.$METHOD($COLLECTION,true) + - metavariable-regex: + metavariable: $METHOD + regex: CreateForX509(Collection|Store) + fix: SslCertificateTrust.$METHOD($COLLECTION,false) + message: Sending the trusted CA list increases the size of the handshake request and can leak system configuration information. + languages: [csharp] + metadata: + references: + - https://docs.microsoft.com/en-us/dotnet/api/system.net.security.sslcertificatetrust.createforx509collection?view=net-6.0#remarks + - https://docs.microsoft.com/en-us/dotnet/api/system.net.security.sslcertificatetrust.createforx509store?view=net-6.0#remarks + cwe: "CWE-200: Exposure of Sensitive Information to an Unauthorized Actor" + owasp: "A03:2017 - Sensitive Data Exposure" + category: correctness + technology: + - .net + confidence: HIGH + severity: WARNING +- id: csharp.lang.security.ad.jwt-tokenvalidationparameters-no-expiry-validation.jwt-tokenvalidationparameters-no-expiry-validation + patterns: + - pattern-either: + - patterns: + - pattern: $LIFETIME = $FALSE + - pattern-inside: new TokenValidationParameters {...} + - patterns: + - pattern: | + (TokenValidationParameters $OPTS). ... .$LIFETIME = $FALSE + - metavariable-regex: + metavariable: $LIFETIME + regex: (RequireExpirationTime|ValidateLifetime) + - metavariable-regex: + metavariable: $FALSE + regex: (false) + - focus-metavariable: $FALSE + fix: | + true + message: >- + The TokenValidationParameters.$LIFETIME is set to $FALSE, this means the JWT tokens lifetime is not + validated. This can lead to an JWT token being used after it has expired, which has security implications. It + is recommended to validate the JWT lifetime to ensure only valid tokens are used. + metadata: + category: security + technology: + - csharp + owasp: + - A02:2017 - Broken Authentication + - A07:2021 - Identification and Authentication Failures + cwe: + - 'CWE-613: Insufficient Session Expiration' + references: + - https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures/ + - https://cwe.mitre.org/data/definitions/613.html + - https://docs.microsoft.com/en-us/dotnet/api/microsoft.identitymodel.tokens.tokenvalidationparameters?view=azure-dotnet + subcategory: + - audit + likelihood: HIGH + impact: MEDIUM + confidence: HIGH + languages: + - csharp + severity: WARNING +- id: csharp.lang.security.cryptography.x509-subject-name-validation.x509-subject-name-validation + severity: WARNING + languages: + - csharp + metadata: + cwe: + - 'CWE-295: Improper Certificate Validation' + owasp: + - A03:2017 - Sensitive Data Exposure + - A07:2021 - Identification and Authentication Failures + references: + - https://docs.microsoft.com/en-us/dotnet/api/system.identitymodel.tokens.issuernameregistry?view=netframework-4.8 + category: security + technology: + - .net + confidence: MEDIUM + subcategory: + - vuln + likelihood: LOW + impact: LOW + message: >- + Validating certificates based on subject name is bad practice. Use the X509Certificate2.Verify() + method instead. + patterns: + - pattern-inside: | + using System.IdentityModel.Tokens; + ... + - pattern-either: + - patterns: + - pattern-either: + - pattern-inside: | + X509SecurityToken $TOK = $RHS; + ... + - pattern-inside: | + $T $M(..., X509SecurityToken $TOK, ...) { + ... + } + - metavariable-pattern: + metavariable: $RHS + pattern-either: + - pattern: $T as X509SecurityToken + - pattern: new X509SecurityToken(...) + - patterns: + - pattern-either: + - pattern-inside: | + X509Certificate2 $CERT = new X509Certificate2(...); + ... + - pattern-inside: | + $T $M(..., X509Certificate2 $CERT, ...) { + ... + } + - pattern-inside: | + foreach (X509Certificate2 $CERT in $COLLECTION) { + ... + } + - patterns: + - pattern-either: + - pattern: String.Equals($NAME, "...") + - pattern: String.Equals("...", $NAME) + - pattern: $NAME.Equals("...") + - pattern: $NAME == "..." + - pattern: $NAME != "..." + - pattern: | + "..." == $NAME + - pattern: | + "..." != $NAME + - metavariable-pattern: + metavariable: $NAME + pattern-either: + - pattern: $TOK.Certificate.SubjectName.Name + - pattern: $CERT.SubjectName.Name + - pattern: $CERT.GetNameInfo(...) +- id: csharp.lang.security.cryptography.x509certificate2-privkey.x509certificate2-privkey + severity: WARNING + languages: + - C# + metadata: + cwe: + - 'CWE-310: CWE CATEGORY: Cryptographic Issues' + owasp: + - A02:2021 - Cryptographic Failures + references: + - https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography.x509certificates.x509certificate2.privatekey + category: security + technology: + - .net + confidence: LOW + subcategory: + - audit + likelihood: LOW + impact: LOW + message: >- + X509Certificate2.PrivateKey is obsolete. Use a method such as GetRSAPrivateKey() or GetECDsaPrivateKey(). + Alternatively, use the CopyWithPrivateKey() method to create a new instance with a private key. Further, + if you set X509Certificate2.PrivateKey to `null` or set it to another key without deleting it first, + the private key will + be left on disk. + patterns: + - pattern-inside: | + using System.Security.Cryptography; + ... + - pattern-either: + - pattern-inside: | + X509Certificate2Collection $COLLECTION = ...; + ... + - pattern-inside: | + X509Certificate2 $CERT = ...; + ... + - pattern: $CERT.PrivateKey +- id: csharp.lang.security.cryptography.unsigned-security-token.unsigned-security-token + patterns: + - pattern: RequireSignedTokens = false + - pattern-inside: | + new TokenValidationParameters { + ... + } + fix: RequireSignedTokens = true + message: Accepting unsigned security tokens as valid security tokens allows an attacker to remove its + signature and potentially forge an identity. As a fix, set RequireSignedTokens to be true. + metadata: + category: security + technology: + - csharp + owasp: + - A02:2021 - Cryptographic Failures + cwe: + - 'CWE-347: Improper Verification of Cryptographic Signature' + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control/ + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures/ + - https://cwe.mitre.org/data/definitions/347 + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + languages: + - csharp + severity: ERROR +- id: csharp.lang.security.filesystem.unsafe-path-combine.unsafe-path-combine + mode: taint + pattern-sources: + - patterns: + - pattern: $A + - pattern-inside: | + Path.Combine(...,$A,...) + - pattern-inside: | + public $TYPE $M(...,$A,...){...} + - pattern-not-inside: | + <... Path.GetFileName($A) != $A ...> + pattern-sinks: + - patterns: + - focus-metavariable: $X + - pattern: | + File.$METHOD($X,...) + - metavariable-regex: + metavariable: $METHOD + regex: (?i)^(read|write) + pattern-sanitizers: + - pattern: | + Path.GetFileName(...) + - patterns: + - pattern-inside: | + $X = Path.GetFileName(...); + ... + - pattern: $X + - patterns: + - pattern: $X + - pattern-inside: | + if(<... Path.GetFileName($X) != $X ...>){ + ... + throw new $EXCEPTION(...); + } + ... + message: String argument $A is used to read or write data from a file via Path.Combine without direct + sanitization via Path.GetFileName. If the path is user-supplied data this can lead to path traversal. + languages: + - csharp + severity: WARNING + metadata: + category: security + confidence: MEDIUM + references: + - https://www.praetorian.com/blog/pathcombine-security-issues-in-aspnet-applications/ + - https://docs.microsoft.com/en-us/dotnet/api/system.io.path.combine?view=net-6.0#remarks + technology: + - .net + cwe: + - "CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')" + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: LOW + impact: MEDIUM +- id: csharp.lang.security.http.http-listener-wildcard-bindings.http-listener-wildcard-bindings + severity: WARNING + languages: + - C# + metadata: + cwe: + - 'CWE-706: Use of Incorrectly-Resolved Name or Reference' + owasp: + - A01:2021 - Broken Access Control + references: + - https://docs.microsoft.com/en-us/dotnet/api/system.net.httplistener?view=net-6.0 + category: security + technology: + - .net + confidence: MEDIUM + subcategory: + - vuln + likelihood: LOW + impact: LOW + message: >- + The top level wildcard bindings $PREFIX leaves your application open to security vulnerabilities and + give attackers more control over where traffic is routed. + If you must use wildcards, consider using subdomain wildcard binding. For example, you can use "*.asdf.gov" + if you own all of "asdf.gov". + patterns: + - pattern-inside: | + using System.Net; + ... + - pattern: $LISTENER.Prefixes.Add("$PREFIX") + - metavariable-regex: + metavariable: $PREFIX + regex: |- + (http|https)://(\*|\+)(.[a-zA-Z]{2,})?:[0-9]+ +- id: csharp.lang.security.injections.os-command.os-command-injection + severity: ERROR + languages: + - csharp + metadata: + cwe: + - "CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')" + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + references: + - https://owasp.org/www-community/attacks/Command_Injection + category: security + technology: + - .net + confidence: LOW + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH + message: >- + The software constructs all or part of an OS command using externally-influenced input from an upstream + component, but + it does not neutralize or incorrectly neutralizes special elements that could modify the intended + OS command when it is + sent to a downstream component. + patterns: + - pattern-inside: | + using System.Diagnostics; + ... + - pattern-inside: | + public $T $F(..., $ARG, ...) + { + ... + } + - pattern-either: + - patterns: + - pattern: | + Process.Start($ARG, ...); + - focus-metavariable: $ARG + - patterns: + - pattern-inside: | + Process $PROC = new Process(); + ... + - pattern-either: + - pattern-inside: | + $PROC.StartInfo.FileName = $ARG; + ... + - pattern-inside: | + $PROC.StartInfo.Arguments = <... $ARG ...>; + ... + - pattern: | + $PROC.Start(); + - patterns: + - patterns: + - pattern-inside: | + ProcessStartInfo $PSINFO = new ProcessStartInfo() + { + ... + }; + ... + - pattern-either: + - pattern-inside: | + FileName = $ARG; + ... + - pattern-inside: | + Arguments = <... $ARG ...>; + ... + - pattern: | + Process.Start($PSINFO); + - focus-metavariable: $PSINFO + - patterns: + - pattern-inside: | + Process $PROC = new Process() + { + StartInfo = new ProcessStartInfo() + { + ... + } + }; + ... + - pattern-either: + - pattern-inside: | + FileName = $ARG; + ... + - pattern-inside: | + Arguments = $ARG; + ... + - pattern: | + $PROC.Start(); +- id: csharp.lang.security.insecure-deserialization.binary-formatter.insecure-binaryformatter-deserialization + severity: WARNING + languages: + - C# + metadata: + cwe: + - 'CWE-502: Deserialization of Untrusted Data' + owasp: + - A08:2017 - Insecure Deserialization + - A08:2021 - Software and Data Integrity Failures + references: + - https://docs.microsoft.com/en-us/dotnet/standard/serialization/binaryformatter-security-guide + category: security + technology: + - .net + confidence: HIGH + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: HIGH + message: >- + The BinaryFormatter type is dangerous and is not recommended for data processing. Applications should + stop using BinaryFormatter + as soon as possible, even if they believe the data they're processing to be trustworthy. BinaryFormatter + is insecure and can't be made secure + patterns: + - pattern-inside: | + using System.Runtime.Serialization.Formatters.Binary; + ... + - pattern: | + new BinaryFormatter(); +- id: csharp.lang.security.insecure-deserialization.data-contract-resolver.data-contract-resolver + severity: WARNING + languages: + - C# + metadata: + cwe: + - 'CWE-502: Deserialization of Untrusted Data' + owasp: + - A08:2017 - Insecure Deserialization + - A08:2021 - Software and Data Integrity Failures + references: + - https://docs.microsoft.com/en-us/dotnet/standard/serialization/binaryformatter-security-guide + category: security + technology: + - .net + confidence: LOW + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH + message: >- + Only use DataContractResolver if you are completely sure of what information is being serialized. + Malicious types can cause unexpected behavior. + patterns: + - pattern: | + class $MYDCR : DataContractResolver { ... } +- id: csharp.lang.security.insecure-deserialization.fast-json.insecure-fastjson-deserialization + severity: WARNING + languages: + - C# + metadata: + cwe: + - 'CWE-502: Deserialization of Untrusted Data' + owasp: + - A08:2017 - Insecure Deserialization + - A08:2021 - Software and Data Integrity Failures + references: + - https://github.com/mgholam/fastJSON#security-warning-update + category: security + technology: + - .net + confidence: LOW + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH + message: >- + $type extension has the potential to be unsafe, so use it with common sense and known json sources + and not public facing + ones to be safe + patterns: + - pattern-inside: | + using fastJSON; + ... + - pattern: | + new JSONParameters + { + BadListTypeChecking = false + } +- id: csharp.lang.security.insecure-deserialization.fs-pickler.insecure-fspickler-deserialization + severity: WARNING + languages: + - C# + metadata: + cwe: + - 'CWE-502: Deserialization of Untrusted Data' + owasp: + - A08:2017 - Insecure Deserialization + - A08:2021 - Software and Data Integrity Failures + references: + - https://mbraceproject.github.io/FsPickler/tutorial.html#Disabling-Subtype-Resolution + category: security + technology: + - .net + confidence: MEDIUM + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: LOW + impact: HIGH + message: >- + The FsPickler is dangerous and is not recommended for data processing. Default configuration tend + to insecure deserialization + vulnerability. + patterns: + - pattern-inside: | + using MBrace.FsPickler.Json; + ... + - pattern: | + FsPickler.CreateJsonSerializer(); +- id: csharp.lang.security.insecure-deserialization.insecure-typefilterlevel-full.insecure-typefilterlevel-full + severity: WARNING + languages: + - C# + metadata: + cwe: + - 'CWE-502: Deserialization of Untrusted Data' + owasp: + - A08:2017 - Insecure Deserialization + - A08:2021 - Software and Data Integrity Failures + references: + - https://docs.microsoft.com/en-us/dotnet/api/system.runtime.serialization.formatters.typefilterlevel?view=net-6.0 + - https://www.synacktiv.com/en/publications/izi-izi-pwn2own-ics-miami.html + category: security + technology: + - .net + confidence: LOW + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH + message: >- + Using a .NET remoting service can lead to RCE, even if you try to configure TypeFilterLevel. + Recommended to switch from .NET Remoting to WCF https://docs.microsoft.com/en-us/dotnet/framework/wcf/migrating-from-net-remoting-to-wcf + pattern-either: + - patterns: + - pattern-either: + - pattern: new BinaryServerFormatterSinkProvider { TypeFilterLevel = $LEVEL } + - patterns: + - pattern-inside: | + $TYPE $SP = new BinaryServerFormatterSinkProvider(...); + ... + - pattern: | + $SP.TypeFilterLevel = $LEVEL + - metavariable-regex: + metavariable: $LEVEL + regex: (.*)TypeFilterLevel\.(Full|Low) + - patterns: + - pattern-inside: | + $DICT["typeFilterLevel"] = $VAL; + ... + - pattern: new BinaryServerFormatterSinkProvider(..., $DICT, ...) + - metavariable-regex: + metavariable: $VAL + regex: (\"Full\"|\"Low\") +- id: csharp.lang.security.insecure-deserialization.javascript-serializer.insecure-javascriptserializer-deserialization + severity: ERROR + languages: + - C# + metadata: + cwe: + - 'CWE-502: Deserialization of Untrusted Data' + owasp: + - A08:2017 - Insecure Deserialization + - A08:2021 - Software and Data Integrity Failures + references: + - https://docs.microsoft.com/en-us/dotnet/api/system.web.script.serialization.simpletyperesolver?view=netframework-4.8#remarks + category: security + technology: + - .net + confidence: LOW + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + message: >- + The SimpleTypeResolver class is insecure and should not be used. Using SimpleTypeResolver to deserialize + JSON could allow + the remote client to execute malicious code within the app and take control of the web server. + patterns: + - pattern-inside: | + using System.Web.Script.Serialization; + ... + - pattern: | + new JavaScriptSerializer((SimpleTypeResolver $RESOLVER)) +- id: csharp.lang.security.insecure-deserialization.los-formatter.insecure-losformatter-deserialization + severity: WARNING + languages: + - C# + metadata: + cwe: + - 'CWE-502: Deserialization of Untrusted Data' + owasp: + - A08:2017 - Insecure Deserialization + - A08:2021 - Software and Data Integrity Failures + references: + - https://docs.microsoft.com/en-us/dotnet/api/system.web.ui.losformatter?view=netframework-4.8 + category: security + technology: + - .net + confidence: MEDIUM + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: LOW + impact: HIGH + message: >- + The LosFormatter type is dangerous and is not recommended for data processing. Applications should + stop using LosFormatter + as soon as possible, even if they believe the data they're processing to be trustworthy. LosFormatter + is insecure and + can't be made secure + patterns: + - pattern-inside: | + using System.Web.UI; + ... + - pattern: | + new LosFormatter(); +- id: csharp.lang.security.insecure-deserialization.net-data-contract.insecure-netdatacontract-deserialization + severity: WARNING + languages: + - C# + metadata: + cwe: + - 'CWE-502: Deserialization of Untrusted Data' + owasp: + - A08:2017 - Insecure Deserialization + - A08:2021 - Software and Data Integrity Failures + references: + - https://docs.microsoft.com/en-us/dotnet/api/system.runtime.serialization.netdatacontractserializer?view=netframework-4.8#security + category: security + technology: + - .net + confidence: MEDIUM + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: LOW + impact: HIGH + message: >- + The NetDataContractSerializer type is dangerous and is not recommended for data processing. Applications + should stop using + NetDataContractSerializer as soon as possible, even if they believe the data they're processing to + be trustworthy. NetDataContractSerializer + is insecure and can't be made secure + patterns: + - pattern-inside: | + using System.Runtime.Serialization; + ... + - pattern: | + new NetDataContractSerializer(); +- id: csharp.lang.security.insecure-deserialization.newtonsoft.insecure-newtonsoft-deserialization + patterns: + - pattern-either: + # handles most inline configurations + - pattern: TypeNameHandling = TypeNameHandling.$TYPEHANDLER + - pattern: | + $SETTINGS.TypeNameHandling = TypeNameHandling.$TYPEHANDLER; + ... + JsonConvert.DeserializeObject<$TYPE>(...,$SETTINGS); + - pattern: | + $SETTINGS.TypeNameHandling = TypeNameHandling.$TYPEHANDLER; + ... + JsonConvert.DeserializeObject(...,$SETTINGS); + - pattern-inside: | + using Newtonsoft.Json; + ... + - metavariable-regex: + metavariable: $TYPEHANDLER + regex: (All|Auto|Objects|Arrays) + message: TypeNameHandling $TYPEHANDLER is unsafe and can lead to arbitrary code execution in the context + of the process. Use a custom SerializationBinder whenever using a setting other than TypeNameHandling.None. + languages: + - csharp + severity: WARNING + metadata: + category: security + cwe: + - 'CWE-502: Deserialization of Untrusted Data' + owasp: + - A08:2017 - Insecure Deserialization + - A08:2021 - Software and Data Integrity Failures + references: + - https://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_TypeNameHandling.htm#remarks + technology: + - .net + - newtonsoft + - json + confidence: LOW + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH +- id: csharp.lang.security.insecure-deserialization.soap-formatter.insecure-soapformatter-deserialization + severity: WARNING + languages: + - C# + metadata: + cwe: + - 'CWE-502: Deserialization of Untrusted Data' + owasp: + - A08:2017 - Insecure Deserialization + - A08:2021 - Software and Data Integrity Failures + references: + - https://docs.microsoft.com/en-us/dotnet/api/system.runtime.serialization.formatters.soap.soapformatter?view=netframework-4.8#remarks + category: security + technology: + - .net + confidence: MEDIUM + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: LOW + impact: HIGH + message: >- + The SoapFormatter type is dangerous and is not recommended for data processing. Applications should + stop using SoapFormatter + as soon as possible, even if they believe the data they're processing to be trustworthy. SoapFormatter + is insecure and + can't be made secure + patterns: + - pattern-inside: | + using System.Runtime.Serialization.Formatters.Soap; + ... + - pattern: | + new SoapFormatter(); +- id: csharp.lang.security.memory.memory-marshal-create-span.memory-marshal-create-span + severity: WARNING + languages: + - C# + metadata: + cwe: + - 'CWE-125: Out-of-bounds Read' + owasp: + - A04:2021 - Insecure Design + references: + - https://docs.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.memorymarshal.createspan?view=net-6.0 + - https://docs.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.memorymarshal.createreadonlyspan?view=net-6.0 + category: security + technology: + - .net + confidence: LOW + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + message: >- + MemoryMarshal.CreateSpan and MemoryMarshal.CreateReadOnlySpan should be used with caution, as the + length argument is not checked. + pattern-either: + - pattern: MemoryMarshal.CreateSpan(...) + - pattern: MemoryMarshal.CreateReadOnlySpan(...) +- id: csharp.lang.security.missing-hsts-header.missing-hsts-header + pattern-either: + - patterns: + - pattern-inside: | + public void Configure(...) { + ... + (IApplicationBuilder $APP). ...; + ... + } + - focus-metavariable: $APP + - pattern-not-inside: | + public void Configure(...) { + ... + (IApplicationBuilder $APP).UseHsts(...); + ... + } + - patterns: + - pattern-inside: | + public void ConfigureServices(...) { + ... + (IServiceCollection $SERVICES). ...; + ... + } + - focus-metavariable: $SERVICES + - pattern-not-inside: | + public void ConfigureServices(...) { + ... + (IServiceCollection $SERVICES).AddHsts(...); + ... + } + message: The HSTS HTTP response security header is missing, allowing interaction and communication to + be sent over the insecure HTTP protocol. + metadata: + category: security + technology: + - dotnet + owasp: + - A07:2021 - Identification and Authentication Failures + cwe: + - 'CWE-346: Origin Validation Error' + references: + - https://cwe.mitre.org/data/definitions/346.html + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures/ + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: + - csharp + severity: WARNING +- id: csharp.lang.security.open-redirect.open-redirect + mode: taint + pattern-sources: + - patterns: + - focus-metavariable: $PARAM + - pattern-inside: | + public $TYPE $FUNCNAME (..., string $PARAM, ...) { + ... + } + pattern-sinks: + - patterns: + - pattern: Redirect(...) + - pattern-not-inside: | + if (IsLocalUrl(...)) { + ... + Redirect(...); + ... + } + - pattern-not-inside: | + if ($URL.IsLocalUrl(...)) { + ... + Redirect(...); + ... + } + message: >- + A query string parameter may contain a URL value that could cause the + web application to redirect the request to a malicious website controlled by + an attacker. Make sure to sanitize this parameter sufficiently. + metadata: + category: security + technology: + - csharp + cwe: + - "CWE-601: URL Redirection to Untrusted Site ('Open Redirect')" + references: + - https://cwe.mitre.org/data/definitions/601.html + owasp: + - A01:2021 - Broken Access Control + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: LOW + languages: + - csharp + severity: ERROR +- id: csharp.lang.security.regular-expression-dos.regular-expression-dos-infinite-timeout.regular-expression-dos-infinite-timeout + severity: WARNING + languages: + - C# + metadata: + cwe: + - 'CWE-1333: Inefficient Regular Expression Complexity' + owasp: 'A01:2017 - Injection' + references: + - https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS + - https://docs.microsoft.com/en-us/dotnet/api/system.text.regularexpressions.regex.infinitematchtimeout + - https://docs.microsoft.com/en-us/dotnet/api/system.text.regularexpressions.regex.-ctor?view=net-6.0 + category: security + technology: + - .net + confidence: MEDIUM + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + message: >- + Specifying the regex timeout leaves the system vulnerable to a regex-based Denial of Service (DoS) + attack. Consider setting the timeout to a short amount of time like 2 or 3 seconds. + If you are sure you need an infinite timeout, double check that your context meets the conditions + outlined in the "Notes to Callers" section at the bottom of this page: https://docs.microsoft.com/en-us/dotnet/api/system.text.regularexpressions.regex.-ctor?view=net-6.0 + patterns: + - pattern-inside: | + using System.Text.RegularExpressions; + ... + - pattern-either: + - pattern: new Regex(..., TimeSpan.InfiniteMatchTimeout) + - patterns: + - pattern: new Regex(..., TimeSpan.FromSeconds($TIME)) + - metavariable-comparison: + metavariable: $TIME + comparison: $TIME > 5 + - pattern: new Regex(..., TimeSpan.FromMinutes(...)) + - pattern: new Regex(..., TimeSpan.FromHours(...)) +- id: csharp.lang.security.regular-expression-dos.regular-expression-dos.regular-expression-dos + severity: WARNING + languages: + - C# + metadata: + cwe: + - 'CWE-1333: Inefficient Regular Expression Complexity' + owasp: 'A01:2017 - Injection' + references: + - https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS + - https://docs.microsoft.com/en-us/dotnet/standard/base-types/regular-expressions#regular-expression-examples + category: security + technology: + - .net + confidence: MEDIUM + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + message: >- + When using `System.Text.RegularExpressions` to process untrusted input, pass a timeout. + A malicious user can provide input to `RegularExpressions` that abuses the backtracking behaviour of this regular expression engine. + This will lead to excessive CPU usage, causing a Denial-of-Service attack + patterns: + - pattern-inside: | + using System.Text.RegularExpressions; + ... + - pattern-either: + - pattern: | + public $T $F($X) + { + Regex $Y = new Regex($P); + ... + $Y.Match($X); + } + - pattern: | + public $T $F($X) + { + Regex $Y = new Regex($P, $O); + ... + $Y.Match($X); + } + - pattern: | + public $T $F($X) + { + ... Regex.Match($X, $P); + } + - pattern: | + public $T $F($X) + { + ... Regex.Match($X, $P, $O); + } +- id: csharp.lang.security.sqli.csharp-sqli.csharp-sqli + mode: taint + pattern-sources: + - patterns: + - pattern: | + (string $X) + - pattern-not: | + "..." + pattern-propagators: + - pattern: (StringBuilder $B).$ANY(...,(string $X),...) + from: $X + to: $B + pattern-sinks: + - patterns: + - pattern-either: + - patterns: + - pattern: | + new $PATTERN($CMD,...) + - focus-metavariable: $CMD + - pattern: | + $CMD.$PATTERN = ...; + - metavariable-regex: + metavariable: $PATTERN + regex: ^(SqlCommand|CommandText|OleDbCommand|OdbcCommand|OracleCommand)$ + pattern-sanitizers: + - pattern-either: + - pattern: | + $CMD.Parameters.add(...) + - pattern: | + $CMD.Parameters[$IDX] = ... + by-side-effect: true + message: Detected a formatted string in a SQL statement. This could lead to SQL + injection if variables in the SQL statement are not properly sanitized. + Use a prepared statements instead. You can obtain a PreparedStatement + using 'SqlCommand' and 'SqlParameter'. + metadata: + category: security + technology: + - csharp + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + cwe: + - "CWE-89: Improper Neutralization of Special Elements used in an SQL + Command ('SQL Injection')" + confidence: MEDIUM + references: + - https://owasp.org/Top10/A03_2021-Injection + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH + languages: + - csharp + severity: ERROR +- id: csharp.lang.security.ssrf.http-client.ssrf + severity: ERROR + languages: + - csharp + metadata: + cwe: + - 'CWE-918: Server-Side Request Forgery (SSRF)' + owasp: + - A10:2021 - Server-Side Request Forgery (SSRF) + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet.html + category: security + technology: + - .net + confidence: LOW + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + message: >- + SSRF is an attack vector that abuses an application to interact with the internal/external network + or the machine itself. + patterns: + - pattern-inside: | + using System.Net.Http; + ... + - pattern-either: + - pattern: | + $T $F(..., $X, ...) + { + ... + HttpClient $Y = new HttpClient(); + ... + ... $Y.GetAsync(<... $X ...>, ...); + } + - pattern: | + $T $F(..., $X, ...) + { + ... + $A $B = <... $X ...>; + ... + HttpClient $Y = new HttpClient(); + ... + ... $Y.GetAsync($B, ...); + } + - pattern: | + $T $F(..., $X, ...) + { + ... + HttpClient $Y = new HttpClient(); + ... + ... $Y.GetStringAsync(<... $X ...>); + } + - pattern: | + $T $F(..., $X, ...) + { + ... + $A $B = <... $X ...>; + ... + HttpClient $Y = new HttpClient(); + ... + ... $Y.GetStringAsync($B); + } +- id: csharp.lang.security.ssrf.rest-client.ssrf + severity: ERROR + languages: + - csharp + metadata: + cwe: + - 'CWE-918: Server-Side Request Forgery (SSRF)' + owasp: + - A10:2021 - Server-Side Request Forgery (SSRF) + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet.html + category: security + technology: + - .net + confidence: LOW + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + message: >- + SSRF is an attack vector that abuses an application to interact with the internal/external network + or the machine itself. + patterns: + - pattern-inside: | + using RestSharp; + ... + - pattern-either: + - pattern: | + $T $F(..., $X, ...) + { + ... + ... new RestClient(<... $X ...>); + } + - pattern: | + $T $F(..., $X, ...) + { + ... + $A $B = <... $X ...>; + ... + ... new RestClient($B); + } +- id: csharp.lang.security.ssrf.web-client.ssrf + severity: ERROR + languages: + - csharp + metadata: + cwe: + - 'CWE-918: Server-Side Request Forgery (SSRF)' + owasp: + - A10:2021 - Server-Side Request Forgery (SSRF) + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet.html + category: security + technology: + - .net + confidence: LOW + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + message: >- + SSRF is an attack vector that abuses an application to interact with the internal/external network + or the machine itself. + patterns: + - pattern-inside: | + using System.Net; + ... + - pattern-either: + - pattern: | + $T $F(..., $X, ...) + { + ... + WebClient $Y = new WebClient(); + ... + ... $Y.OpenRead(<... $X ...>); + } + - pattern: | + $T $F(..., $X, ...) + { + ... + $A $B = <... $X ...>; + ... + WebClient $Y = new WebClient(); + ... + ... $Y.OpenRead($B); + } + - pattern: | + $T $F(..., $X, ...) + { + ... + WebClient $Y = new WebClient(); + ... + ... $Y.OpenReadAsync(<... $X ...>, ...); + } + - pattern: | + $T $F(..., $X, ...) + { + ... + $A $B = <... $X ...>; + ... + WebClient $Y = new WebClient(); + ... + ... $Y.OpenReadAsync($B, ...); + } + - pattern: | + $T $F(..., $X, ...) + { + ... + WebClient $Y = new WebClient(); + ... + ... $Y.DownloadString(<... $X ...>); + } + - pattern: | + $T $F(..., $X, ...) + { + ... + $A $B = <... $X ...>; + ... + WebClient $Y = new WebClient(); + ... + ... $Y.DownloadString($B); + } +- id: csharp.lang.security.ssrf.web-request.ssrf + severity: ERROR + languages: + - csharp + metadata: + cwe: + - 'CWE-918: Server-Side Request Forgery (SSRF)' + owasp: + - A10:2021 - Server-Side Request Forgery (SSRF) + references: + - https://cwe.mitre.org/data/definitions/918.html + - https://cheatsheetseries.owasp.org/cheatsheets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet.html + category: security + technology: + - .net + confidence: LOW + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + message: >- + The web server receives a URL or similar request from an upstream component and retrieves the contents + of this URL, but + it does not sufficiently ensure that the request is being sent to the expected destination. + Many different options exist to fix this issue depending the use case (Application can send request + only to identified + and trusted applications, Application can send requests to ANY external IP address or domain name). + patterns: + - pattern-inside: | + using System.Net; + ... + - pattern-either: + - pattern: | + $T $F(..., $X, ...) + { + ... + ... WebRequest.Create(<... $X ...>); + } + - pattern: | + $T $F($X) + { + ... + $A $B = <... $X ...>; + ... + ... WebRequest.Create($B); + } + - pattern: | + $T $F($X) + { + ... + $A $B = <... $X ...>; + ... + $C $D = <... $B ...>; + ... + ... WebRequest.Create($D); + } +- id: csharp.lang.security.stacktrace-disclosure.stacktrace-disclosure + patterns: + - pattern: $APP.UseDeveloperExceptionPage(...); + - pattern-not-inside: | + if ($ENV.IsDevelopment(...)) { + ... + $APP.UseDeveloperExceptionPage(...); + ... + } + message: >- + Stacktrace information is displayed in a non-Development environment. + Accidentally disclosing sensitive stack trace information in a production + environment aids an attacker in reconnaissance and information gathering. + metadata: + category: security + technology: + - csharp + owasp: + - A06:2017 - Security Misconfiguration + - A04:2021 - Insecure Design + cwe: + - 'CWE-209: Generation of Error Message Containing Sensitive Information' + references: + - https://cwe.mitre.org/data/definitions/209.html + - https://owasp.org/Top10/A04_2021-Insecure_Design/ + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: HIGH + languages: + - csharp + severity: WARNING +- id: csharp.lang.security.xxe.xmldocument-unsafe-parser-override.xmldocument-unsafe-parser-override + mode: taint + pattern-sources: + - patterns: + - focus-metavariable: $ARG + - pattern-inside: | + public $T $M(...,string $ARG,...){...} + pattern-sinks: + - patterns: + - pattern: | + $XMLDOCUMENT.$METHOD(...) + - pattern-inside: | + XmlDocument $XMLDOCUMENT = new XmlDocument(...); + ... + $XMLDOCUMENT.XmlResolver = new XmlUrlResolver(...); + ... + message: XmlReaderSettings found with DtdProcessing.Parse on an XmlReader handling a string argument + from a public method. Enabling Document Type Definition (DTD) parsing may cause XML External Entity + (XXE) injection if supplied with user-controllable data. + languages: + - csharp + severity: WARNING + metadata: + category: security + references: + - https://www.jardinesoftware.net/2016/05/26/xxe-and-net/ + - https://docs.microsoft.com/en-us/dotnet/api/system.xml.xmldocument.xmlresolver?view=net-6.0#remarks + technology: + - .net + - xml + cwe: + - 'CWE-611: Improper Restriction of XML External Entity Reference' + owasp: + - A04:2017 - XML External Entities (XXE) + - A05:2021 - Security Misconfiguration + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + impact: MEDIUM + likelihood: LOW + confidence: MEDIUM +- id: csharp.lang.security.xxe.xmlreadersettings-unsafe-parser-override.xmlreadersettings-unsafe-parser-override + mode: taint + pattern-sources: + - patterns: + - focus-metavariable: $ARG + - pattern-inside: | + public $T $M(...,string $ARG,...){...} + pattern-sinks: + - patterns: + - pattern: | + XmlReader $READER = XmlReader.Create(...,$RS,...); + - pattern-inside: | + XmlReaderSettings $RS = new XmlReaderSettings(); + ... + $RS.DtdProcessing = DtdProcessing.Parse; + ... + message: XmlReaderSettings found with DtdProcessing.Parse on an XmlReader handling a string argument + from a public method. Enabling Document Type Definition (DTD) parsing may cause XML External Entity + (XXE) injection if supplied with user-controllable data. + languages: + - csharp + severity: WARNING + metadata: + category: security + references: + - https://www.jardinesoftware.net/2016/05/26/xxe-and-net/ + - https://docs.microsoft.com/en-us/dotnet/api/system.xml.xmldocument.xmlresolver?view=net-6.0#remarks + technology: + - .net + - xml + cwe: + - 'CWE-611: Improper Restriction of XML External Entity Reference' + owasp: + - A04:2017 - XML External Entities (XXE) + - A05:2021 - Security Misconfiguration + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + impact: MEDIUM + likelihood: LOW + confidence: MEDIUM +- id: csharp.lang.security.xxe.xmltextreader-unsafe-defaults.xmltextreader-unsafe-defaults + mode: taint + pattern-sources: + - patterns: + - focus-metavariable: $ARG + - pattern-inside: | + public $T $M(...,string $ARG,...){...} + pattern-sinks: + - patterns: + - pattern: | + $READER.$METHOD(...) + - pattern-not-inside: | + $READER.DtdProcessing = DtdProcessing.Prohibit; + ... + - pattern-inside: | + XmlTextReader $READER = new XmlTextReader(...); + ... + message: XmlReaderSettings found with DtdProcessing.Parse on an XmlReader handling a string argument + from a public method. Enabling Document Type Definition (DTD) parsing may cause XML External Entity + (XXE) injection if supplied with user-controllable data. + languages: + - csharp + severity: WARNING + metadata: + category: security + references: + - https://www.jardinesoftware.net/2016/05/26/xxe-and-net/ + - https://docs.microsoft.com/en-us/dotnet/api/system.xml.xmldocument.xmlresolver?view=net-6.0#remarks + technology: + - .net + - xml + cwe: + - 'CWE-611: Improper Restriction of XML External Entity Reference' + owasp: + - A04:2017 - XML External Entities (XXE) + - A05:2021 - Security Misconfiguration + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + impact: MEDIUM + likelihood: LOW + confidence: MEDIUM +- id: csharp.razor.security.html-raw-json.html-raw-json + patterns: + - pattern-either: + - pattern: '@Html.Raw(Json.Encode(...))' + - pattern: '@Html.Raw(JsonConvert.SerializeObject(...))' + - pattern: '@Html.Raw(...ToJson(...))' + message: Unencoded JSON in HTML context is vulnerable to cross-site scripting, because `` is + not properly encoded. + languages: + - generic + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + category: security + technology: + - razor + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + references: + - https://owasp.org/Top10/A03_2021-Injection + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + paths: + include: + - '*.cshtml' + severity: ERROR +- id: dockerfile.audit.dockerfile-source-not-pinned.dockerfile-source-not-pinned + patterns: + - pattern-either: + - patterns: + - pattern: FROM $IMAGE:$VERSION@$HASH + - metavariable-regex: + metavariable: $HASH + regex: (?!sha256:) + - patterns: + - pattern: FROM $IMAGE + - pattern: FROM $IMAGE:$VERSION + - pattern-not-inside: FROM $IMAGE:$VERSION@$HASH + message: >- + To ensure reproducible builds, pin Dockerfile `FROM` commands to a specific + hash. You can find the hash by running `docker pull $IMAGE` and then + specify it with `$IMAGE:$VERSION@sha256:` + languages: + - dockerfile + severity: INFO + metadata: + references: + - https://stackoverflow.com/a/33511811/4965 + category: best-practice + technology: + - docker +- id: dockerfile.best-practice.avoid-apk-upgrade.avoid-apk-upgrade + languages: + - dockerfile + message: >- + Packages in base images should be up-to-date, removing the need for + 'apk upgrade'. If packages are out-of-date, consider contacting the + base image maintainer. + severity: INFO + metadata: + source-rule-url: https://github.com/hadolint/hadolint/wiki/DL3017 + references: + - https://github.com/hadolint/hadolint/wiki/DL3017 + category: best-practice + technology: + - dockerfile + pattern: RUN ... apk upgrade ... +- id: dockerfile.best-practice.avoid-apt-get-upgrade.avoid-apt-get-upgrade + message: >- + Packages in base containers should be up-to-date, removing the need + to upgrade or dist-upgrade. If a package is out of date, contact the maintainers. + languages: [dockerfile] + severity: WARNING + metadata: + source-rule-url: https://github.com/hadolint/hadolint/wiki/DL3005 + references: + - https://github.com/hadolint/hadolint/wiki/DL3005 + category: best-practice + technology: + - dockerfile + pattern-either: + - pattern: RUN ... apt-get upgrade ... + - pattern: RUN ... apt-get dist-upgrade ... +- id: dockerfile.best-practice.avoid-dnf-update.avoid-dnf-update + severity: INFO + languages: [dockerfile] + message: >- + Packages in base images should be up-to-date, removing the need for + 'dnf update'. If packages are out-of-date, consider contacting the + base image maintainer. + metadata: + source-rule-url: https://github.com/hadolint/hadolint/wiki/DL3039 + references: + - https://github.com/hadolint/hadolint/wiki/DL3039 + category: best-practice + technology: + - dockerfile + pattern: dnf update +- id: dockerfile.best-practice.avoid-latest-version.avoid-latest-version + message: >- + Images should be tagged with an explicit version to produce + deterministic container images. The 'latest' tag may change + the base container without warning. + severity: WARNING + languages: [dockerfile] + metadata: + source-rule-url: https://github.com/hadolint/hadolint/wiki/DL3007 + references: + - https://github.com/hadolint/hadolint/wiki/DL3007 + category: best-practice + technology: + - dockerfile + pattern: FROM $FROM:latest +- id: dockerfile.best-practice.avoid-platform-with-from.avoid-platform-with-from + severity: INFO + languages: [dockerfile] + pattern: FROM --platform=$PLATFORM $IMAGE + message: >- + Using '--platform' with FROM restricts the image to build on a single platform. + Further, this must be the same as the + build platform. + If you intended to specify the target platform, use the utility 'docker buildx + --platform=' instead. + metadata: + source-rule-url: https://github.com/hadolint/hadolint/wiki/DL3029 + references: + - https://github.com/hadolint/hadolint/wiki/DL3029 + - https://docs.docker.com/buildx/working-with-buildx/ + category: best-practice + technology: + - dockerfile + fix: FROM $IMAGE +- id: dockerfile.best-practice.avoid-yum-update.avoid-yum-update + severity: INFO + languages: [dockerfile] + message: >- + Packages in base images should be up-to-date, removing the need for + 'yum update'. If packages are out-of-date, consider contacting the + base image maintainer. + metadata: + source-rule-url: https://github.com/hadolint/hadolint/wiki/DL3031 + references: + - https://github.com/hadolint/hadolint/wiki/DL3031 + category: best-practice + technology: + - dockerfile + pattern: yum update +- id: dockerfile.best-practice.avoid-zypper-update.avoid-zypper-update + severity: INFO + languages: [dockerfile] + message: >- + Packages in base images should be up-to-date, removing the need for + 'zypper update'. If packages are out-of-date, consider contacting the + base image maintainer. + metadata: + source-rule-url: https://github.com/hadolint/hadolint/wiki/DL3035 + references: + - https://github.com/hadolint/hadolint/wiki/DL3035 + category: best-practice + technology: + - dockerfile + pattern: zypper update ... +- id: dockerfile.best-practice.maintainer-is-deprecated.maintainer-is-deprecated + severity: INFO + languages: [dockerfile] + pattern: MAINTAINER $NAME + message: >- + MAINTAINER has been deprecated. + metadata: + source-rule-url: https://github.com/hadolint/hadolint/wiki/DL4000 + references: + - https://github.com/hadolint/hadolint/wiki/DL4000 + category: best-practice + technology: + - dockerfile + fix: "# MAINTAINER $NAME" +- id: dockerfile.best-practice.missing-apk-no-cache.missing-apk-no-cache + patterns: + - pattern: | + RUN apk $COMMAND ... + - pattern-not-inside: | + RUN apk ... --no-cache ... + languages: + - dockerfile + message: >- + This apk command is missing '--no-cache'. This forces apk to use a package + index instead of a local package cache, removing the need for '--update' + and the deletion of '/var/cache/apk/*'. Add '--no-cache' to your apk command. + severity: INFO + metadata: + source-rule-url: https://github.com/hadolint/hadolint/wiki/DL3019 + references: + - https://github.com/hadolint/hadolint/wiki/DL3019 + category: best-practice + technology: + - dockerfile + fix: RUN apk $COMMAND --no-cache $SOMETHING +- id: dockerfile.best-practice.missing-dnf-assume-yes-switch.missing-dnf-assume-yes-switch + severity: WARNING + languages: [dockerfile] + patterns: + - pattern: | + RUN ... dnf install ... + - pattern-not-inside: | + RUN ... dnf install ... -y ... + - pattern-not-inside: | + RUN ... dnf ... --assumeyes ... + message: >- + This 'dnf install' is missing the '-y' switch. This might stall + builds because it requires human intervention. Add the '-y' switch. + metadata: + source-rule-url: https://github.com/hadolint/hadolint/wiki/DL3038 + references: + - https://github.com/hadolint/hadolint/wiki/DL3038 + category: best-practice + technology: + - dockerfile +- id: dockerfile.best-practice.missing-dnf-clean-all.missing-dnf-clean-all + severity: WARNING + languages: [dockerfile] + patterns: + - pattern: RUN ... dnf ... + - pattern-not-inside: RUN ... && dnf clean all + - pattern-not-inside: RUN ... && \ dnf clean all + message: >- + This dnf command does not end with '&& dnf clean all'. Running 'dnf clean all' will remove cached data and reduce package size. (This must be performed in the same RUN step.) + metadata: + source-rule-url: https://github.com/hadolint/hadolint/wiki/DL3038 + references: + - https://github.com/hadolint/hadolint/wiki/DL3038 + category: best-practice + technology: + - dockerfile +- id: dockerfile.best-practice.missing-image-version.missing-image-version + patterns: + - pattern-either: + - pattern: FROM $IMAGE + - pattern-not: FROM $IMAGE:$VERSION + - pattern-not: FROM $IMAGE@$DIGEST + - pattern-not: FROM $IMAGE:$VERSION@$DIGEST + - pattern-not: FROM scratch + message: >- + Detected docker image with no explicit version attached. + Images should be tagged with an explicit version to produce + deterministic container images -- attach a version when using + `FROM `. + severity: WARNING + languages: [dockerfile] + metadata: + source-rule-url: https://github.com/hadolint/hadolint/wiki/DL3006 + references: + - https://github.com/hadolint/hadolint/wiki/DL3006 + category: best-practice + technology: + - dockerfile +- id: dockerfile.best-practice.missing-no-install-recommends.missing-no-install-recommends + patterns: + - pattern: | + RUN apt-get install ... + - pattern-not: + RUN apt-get install ... --no-install-recommends ... + languages: [dockerfile] + message: >- + This 'apt-get install' is missing '--no-install-recommends'. This prevents + unnecessary packages from being installed, thereby reducing image size. Add + '--no-install-recommends'. + severity: INFO + metadata: + source-rule-url: https://github.com/hadolint/hadolint/wiki/DL3015 + references: + - https://github.com/hadolint/hadolint/wiki/DL3015 + category: best-practice + technology: + - dockerfile +- id: dockerfile.best-practice.missing-pip-no-cache-dir.missing-pip-no-cache-dir + severity: INFO + languages: [dockerfile] + patterns: + - patterns: + - pattern: | + RUN ... $PIP install ... + - pattern-not-inside: | + RUN ... $PIP install ... --no-cache-dir ... + - pattern-not-inside: | + RUN ... $PIP install . ... + - pattern-not-inside: | + ENV ... PIP_NO_CACHE_DIR=$BOOL ... + ... + RUN ... $PIP install ... + - pattern-not-inside: | + ENV ... PIP_NO_CACHE_DIR ... + ... + RUN ... $PIP install ... + - metavariable-regex: + metavariable: $PIP + regex: (pip|pip2|pip3|python -m pip|python3 -m pip) + message: >- + This '$PIP install' is missing '--no-cache-dir'. This flag prevents + package archives from being kept around, thereby reducing image size. + Add '--no-cache-dir'. + metadata: + source-rule-url: https://github.com/hadolint/hadolint/wiki/DL3042 + references: + - https://github.com/hadolint/hadolint/wiki/DL3042 + category: best-practice + technology: + - dockerfile +- id: dockerfile.best-practice.missing-yum-assume-yes-switch.missing-yum-assume-yes-switch + severity: WARNING + languages: [dockerfile] + patterns: + - pattern: | + RUN ... yum install ... + - pattern-not: | + RUN ... yum install ... -y ... + - pattern-not: | + RUN ... yum ... --assumeyes ... + message: >- + This 'yum install' is missing the '-y' switch. This might stall + builds because it requires human intervention. Add the '-y' switch. + metadata: + source-rule-url: https://github.com/hadolint/hadolint/wiki/DL3030 + references: + - https://github.com/hadolint/hadolint/wiki/DL3030 + category: best-practice + technology: + - dockerfile +- id: dockerfile.best-practice.missing-zypper-clean.missing-zypper-clean + severity: WARNING + languages: [dockerfile] + patterns: + - pattern: RUN ... zypper $COMMAND ... + - pattern-not-inside: RUN ... zypper clean + - pattern-not-inside: RUN ... zypper clean + message: >- + This zypper command does not end with '&& zypper clean'. Running 'zypper clean' will remove cached data and reduce package size. (This must be performed in the same RUN step.) + metadata: + source-rule-url: https://github.com/hadolint/hadolint/wiki/DL3036 + references: + - https://github.com/hadolint/hadolint/wiki/DL3036 + category: best-practice + technology: + - dockerfile +- id: dockerfile.best-practice.nonsensical-command.nonsensical-command + patterns: + - pattern: RUN $CMD ... + - metavariable-regex: + metavariable: $CMD + regex: (shutdown|service|ps|free|top|kill|mount|ifconfig|nano|vim) + message: >- + Some commands such as `$CMD` do not make sense in a container. Do not use + these. + severity: WARNING + languages: [dockerfile] + metadata: + source-rule-url: https://github.com/hadolint/hadolint/wiki/DL3001 + references: + - https://github.com/hadolint/hadolint/wiki/DL3001 + category: best-practice + technology: + - dockerfile +- id: dockerfile.best-practice.prefer-apt-get.prefer-apt-get + severity: INFO + languages: [dockerfile] + patterns: + - pattern: RUN apt ... + - pattern-not: RUN apt-get ... + message: >- + 'apt-get' is preferred as an unattended tool for stability. 'apt' is discouraged. + metadata: + source-rule-url: https://github.com/hadolint/hadolint/wiki/DL3027 + references: + - https://github.com/hadolint/hadolint/wiki/DL3027 + category: best-practice + technology: + - dockerfile +- id: dockerfile.best-practice.prefer-copy-over-add.prefer-copy-over-add + severity: INFO + languages: [dockerfile] + message: >- + The ADD command will accept and include files from a URL and automatically extract + archives. This potentially exposes the container to a man-in-the-middle attack or + other attacks if a malicious actor can tamper with the source archive. Since + ADD can have this and other unexpected side effects, the use of the more explicit + COPY command is preferred. + metadata: + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Docker_Security_Cheat_Sheet.html + category: best-practice + technology: + - dockerfile + patterns: + - pattern: | + ADD $FROM $TO + - metavariable-regex: + metavariable: $FROM + regex: (^[A-Za-z]+:\/\/|.*[.](gz|bz2|zip|tar)$) + - focus-metavariable: $FROM +- id: dockerfile.best-practice.prefer-json-notation.prefer-json-notation + severity: INFO + languages: [dockerfile] + message: >- + Prefer JSON notation when using CMD or ENTRYPOINT. This allows signals to be passed + from the OS. + metadata: + source-rule-url: https://github.com/hadolint/hadolint/wiki/DL3025 + references: + - https://github.com/hadolint/hadolint/wiki/DL3025 + - https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#cmd + category: best-practice + technology: + - dockerfile + pattern-either: + - patterns: + - pattern: CMD $WORD ... + - pattern-not-inside: CMD [...] + - patterns: + - pattern: ENTRYPOINT $WORD ... + - pattern-not-inside: ENTRYPOINT [...] +- id: dockerfile.best-practice.remove-package-cache.remove-package-cache + patterns: + - pattern-not-inside: RUN ... && apt-get clean ... + - pattern: RUN ... apt-get update ... + - pattern: apt-get update + message: + The package cache was not deleted after running 'apt-get update', which increases the size of the image. Remove + the package cache by appending '&& apt-get clean' at the end of apt-get command chain. + severity: WARNING + languages: [dockerfile] + metadata: + source-rule-url: https://github.com/hadolint/hadolint/wiki/DL3009 + references: + - https://github.com/hadolint/hadolint/wiki/DL3009 + category: best-practice + technology: + - dockerfile + license: Commons Clause License Condition v1.0[LGPL-2.1-only] +- id: dockerfile.best-practice.remove-package-lists.remove-package-lists + patterns: + - pattern-not-inside: RUN ... rm -rf /var/lib/apt/lists/* + - pattern: RUN apt-get update ... + - pattern: apt-get update + message: >- + The package lists were not deleted after running 'apt-get update', which + increases the size of the image. + Remove the package lists by appending '&& rm -rf /var/lib/apt/lists/*' at the + end + of apt-get command chain. + severity: WARNING + languages: [dockerfile] + metadata: + source-rule-url: https://github.com/hadolint/hadolint/wiki/DL3009 + references: + - https://github.com/hadolint/hadolint/wiki/DL3009 + category: best-practice + technology: + - dockerfile +- id: dockerfile.best-practice.set-pipefail.set-pipefail + languages: [dockerfile] + message: >- + Only the exit code from the final command in this RUN instruction will be evaluated unless 'pipefail' is set. + If you want to fail the command at any stage in the pipe, set 'pipefail' by including 'SHELL ["/bin/bash", "-o", "pipefail", "-c"] before the command. + If you're using alpine and don't have bash installed, communicate this explicitly with `SHELL ["/bin/ash"]`. + metadata: + references: + - https://github.com/hadolint/hadolint/wiki/DL4006 + source-rule-url: https://github.com/hadolint/hadolint/wiki/DL4006 + category: best-practice + technology: + - dockerfile + patterns: + - pattern-either: + - pattern: RUN ... | ... + - pattern: RUN ... || ... + - pattern-not-inside: | + SHELL [..., "pipefail", ...] + ... + RUN ... | ... + - pattern-not-inside: | + SHELL ["/bin/ash", ...] + ... + RUN ... | ... + severity: WARNING +- id: dockerfile.best-practice.use-either-wget-or-curl.use-either-wget-or-curl + severity: INFO + languages: [dockerfile] + message: >- + 'wget' and 'curl' are similar tools. Choose one and do not install the other to decrease image size. + metadata: + source-rule-url: https://github.com/hadolint/hadolint/wiki/DL4001 + references: + - https://github.com/hadolint/hadolint/wiki/DL4001 + category: best-practice + technology: + - dockerfile + pattern-either: + - pattern: | + RUN wget ... + ... + RUN curl ... + - pattern: | + RUN curl ... + ... + RUN wget ... +- id: dockerfile.best-practice.use-shell-instruction.use-shell-instruction + severity: WARNING + languages: [dockerfile] + pattern: | + RUN ln ... $SHELL /bin/sh + message: >- + Use the SHELL instruction to set the default shell instead of overwriting '/bin/sh'. + metadata: + source-rule-url: https://github.com/hadolint/hadolint/wiki/DL4005 + references: + - https://github.com/hadolint/hadolint/wiki/DL4005 + category: best-practice + technology: + - dockerfile + fix: SHELL ["$SHELL", "-c"] +- id: dockerfile.best-practice.use-workdir.use-workdir + options: + implicit_deep_exprstmt: false + patterns: + - pattern-either: + - pattern-inside: | + RUN $ CMD ... + - pattern-inside: | + RUN $CMD ... && ... + - metavariable-pattern: + metavariable: $CMD + pattern: cd + - focus-metavariable: $CMD + message: >- + As recommended by Docker's documentation, it is best to use 'WORKDIR' + instead of 'RUN cd ...' for improved clarity and reliability. Also, 'RUN cd + ...' may not work as expected in a container. + severity: WARNING + languages: [dockerfile] + metadata: + source-rule-url: https://github.com/hadolint/hadolint/wiki/DL3003 + references: + - https://github.com/hadolint/hadolint/wiki/DL3003 + category: best-practice + technology: + - dockerfile +- id: dockerfile.correctness.invalid-port.invalid-port + message: Detected an invalid port number. Valid ports are 0 through 65535. + severity: ERROR + languages: + - dockerfile + metadata: + source-rule-url: https://github.com/hadolint/hadolint/wiki/DL3011 + references: + - https://github.com/hadolint/hadolint/wiki/DL3011 + category: correctness + technology: + - dockerfile + pattern-either: + - patterns: + - pattern: EXPOSE $PORT + - metavariable-comparison: + metavariable: $PORT + comparison: int($PORT) > 65535 +- id: dockerfile.correctness.missing-assume-yes-switch.missing-assume-yes-switch + patterns: + - pattern: | + RUN ... apt-get install ... $MULTIFLAG ... + - pattern-not: | + RUN ... apt-get install ... --assume-yes ... + - pattern-not: | + RUN ... apt-get install ... --yes ... + - pattern-not: | + RUN ... apt-get install ... -y ... + - metavariable-regex: + metavariable: $MULTIFLAG + regex: (^([^-])|(-[^y]+)$) + languages: + - dockerfile + message: This 'apt-get install' is missing the '-y' switch. This might stall + builds because it requires human intervention. Add the '-y' switch. + severity: WARNING + metadata: + source-rule-url: https://github.com/hadolint/hadolint/wiki/DL3014 + references: + - https://github.com/hadolint/hadolint/wiki/DL3014 + category: correctness + technology: + - dockerfile +- id: dockerfile.correctness.multiple-entrypoint-instructions.multiple-entrypoint-instructions + severity: ERROR + languages: [dockerfile] + patterns: + - pattern: | + ENTRYPOINT ... + ... + $ENTRYPOINT_INSTR + # Restrict the match to just the second ENTRYPOINT instruction. + # This avoids producing unstable findings due to capturing + # many lines of irrelevant code with the ellipsis. + - metavariable-pattern: + metavariable: $ENTRYPOINT_INSTR + pattern: | + ENTRYPOINT ... + - focus-metavariable: $ENTRYPOINT_INSTR + message: >- + Multiple ENTRYPOINT instructions were found. Only the last one + will take effect. + metadata: + source-rule-url: https://github.com/hadolint/hadolint/wiki/DL4004 + references: + - https://github.com/hadolint/hadolint/wiki/DL4004 + - https://kapeli.com/cheat_sheets/Dockerfile.docset/Contents/Resources/Documents/index#//dash_ref_Instructions/Entry/ENTRYPOINT/0 + category: correctness + technology: + - dockerfile +- id: dockerfile.security.last-user-is-root.last-user-is-root + patterns: + - pattern: USER root + - pattern-not-inside: + patterns: + - pattern: | + USER root + ... + USER $X + - metavariable-pattern: + metavariable: $X + patterns: + - pattern-not: root + message: >- + The last user in the container is 'root'. This is a security + hazard because if an attacker gains control of the container + they will have root access. Switch back to another user after + running commands as 'root'. + severity: ERROR + languages: + - dockerfile + metadata: + cwe: + - 'CWE-269: Improper Privilege Management' + source-rule-url: https://github.com/hadolint/hadolint/wiki/DL3002 + references: + - https://github.com/hadolint/hadolint/wiki/DL3002 + category: security + technology: + - dockerfile + confidence: MEDIUM + owasp: + - A04:2021 - Insecure Design + subcategory: + - audit + likelihood: MEDIUM + impact: MEDIUM +- id: dockerfile.security.missing-user-entrypoint.missing-user-entrypoint + patterns: + - pattern: | + ENTRYPOINT $...VARS + - pattern-not-inside: | + USER $USER + ... + fix: | + USER non-root + ENTRYPOINT $...VARS + message: By not specifying a USER, a program in the container may run as 'root'. This is a security + hazard. If an attacker can control a process running as root, they may have control over the container. + Ensure that the last USER in a Dockerfile is a USER other than 'root'. + severity: ERROR + languages: + - dockerfile + metadata: + cwe: + - 'CWE-269: Improper Privilege Management' + category: security + technology: + - dockerfile + confidence: MEDIUM + owasp: + - A04:2021 - Insecure Design + references: + - https://owasp.org/Top10/A04_2021-Insecure_Design + subcategory: + - audit + likelihood: LOW + impact: MEDIUM +- id: dockerfile.security.missing-user.missing-user + patterns: + - pattern: | + CMD $...VARS + - pattern-not-inside: | + USER $USER + ... + fix: | + USER non-root + CMD $...VARS + message: By not specifying a USER, a program in the container may run as 'root'. This is a security + hazard. If an attacker can control a process running as root, they may have control over the container. + Ensure that the last USER in a Dockerfile is a USER other than 'root'. + severity: ERROR + languages: + - dockerfile + metadata: + cwe: + - 'CWE-269: Improper Privilege Management' + category: security + technology: + - dockerfile + confidence: MEDIUM + owasp: + - A04:2021 - Insecure Design + references: + - https://owasp.org/Top10/A04_2021-Insecure_Design + subcategory: + - audit + likelihood: LOW + impact: MEDIUM +- id: dockerfile.security.no-sudo-in-dockerfile.no-sudo-in-dockerfile + patterns: + - pattern: | + RUN sudo ... + message: >- + Avoid using sudo in Dockerfiles. Running processes as a non-root user can help + reduce the potential impact of configuration errors and security vulnerabilities. + metadata: + category: security + technology: + - dockerfile + cwe: + - 'CWE-250: Execution with Unnecessary Privileges' + owasp: + - A05:2021 - Security Misconfiguration + references: + - https://cwe.mitre.org/data/definitions/250.html + - https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#user + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: HIGH + languages: + - dockerfile + severity: WARNING +- id: dockerfile.security.secret-in-build-arg.secret-in-build-arg + patterns: + - pattern-either: + - pattern: ARG $ARG + - pattern: ARG $ARG=... + - metavariable-regex: + metavariable: $ARG + regex: (?i).*(password|secret|token|key|cert|api|auth) + message: >- + Docker build time arguments are not suited for secrets, because the + argument values are saved with the image. Running `docker image history` on the + image will show information on how the image was built, including arguments. If + these contain plain text secrets, anyone with access to the docker image can access + those secrets and exploit them. + metadata: + category: security + technology: + - dockerfile + cwe: + - 'CWE-538: Insertion of Sensitive Information into Externally-Accessible File or Directory' + owasp: + - A01:2021 - Broken Access Control + references: + - https://cwe.mitre.org/data/definitions/538.html + - https://docs.docker.com/engine/reference/builder/#arg + subcategory: + - audit + likelihood: LOW + impact: HIGH + confidence: LOW + languages: + - dockerfile + severity: WARNING +- id: elixir.lang.best-practice.deprecated-bnot-operator.deprecated_bnot_operator + message: >- + The bitwise operator (`^^^`) is already deprecated. Please use `Bitwise.bnot($VAL)` instead. + severity: WARNING + languages: + - elixir + pattern: ~~~$VAL + fix: Bitwise.bnot($VAL) + metadata: + references: + - https://github.com/elixir-lang/elixir/commit/f1b9d3e818e5bebd44540f87be85979f24b9abfc + category: best-practice + technology: + - elixir +- id: elixir.lang.best-practice.deprecated-bxor-operator.deprecated_bxor_operator + message: >- + The bitwise operator (`^^^`) is already deprecated. Please use `Bitwise.bxor($LEFT, $RIGHT)` instead. + severity: WARNING + languages: + - elixir + pattern: $LEFT ^^^ $RIGHT + fix: Bitwise.bxor($LEFT, $RIGHT) + metadata: + references: + - https://github.com/elixir-lang/elixir/commit/c9a171da5b25e0eb5d1da3b04c622f8b79a8aff4 + category: best-practice + technology: + - elixir +- id: elixir.lang.best-practice.deprecated-calendar-iso-day-of-week-3.deprecated_calendar_iso_day_of_week_3 + message: >- + `Calendar.ISO.day_of_week/3` is already deprecated. Please use `Calendar.ISO.day_of_week/4` instead. + severity: WARNING + languages: + - elixir + pattern: $VAR = Calendar.ISO.day_of_week($YEAR, $MONTH, $DAY) + fix: | + {$VAR, _, _} = Calendar.ISO.day_of_week($YEAR, $MONTH, $DAY, :default) + metadata: + references: + - https://github.com/elixir-lang/elixir/releases/tag/v1.15.0 + category: best-practice + technology: + - elixir +- id: elixir.lang.best-practice.deprecated-use-bitwise.deprecated_use_bitwise + message: >- + The syntax `use Bitwise` is already deprecated. Please use `import Bitwise` instead. + severity: WARNING + languages: + - elixir + pattern: use Bitwise + fix: import Bitwise + metadata: + references: + - https://github.com/elixir-lang/elixir/commit/f1b9d3e818e5bebd44540f87be85979f24b9abfc + category: best-practice + technology: + - elixir +- id: elixir.lang.best-practice.enum-map-into.enum_map_into + message: >- + Using `Enum.into/3` is more efficient than using `Enum.map/2 |> Enum.into/2`. + severity: WARNING + languages: + - elixir + pattern-either: + - pattern: | + Enum.into(Enum.map($E, $FUN), $INTO) + - pattern: | + Enum.map($E, $FUN) + |> Enum.into($INTO) + - pattern: | + $E + |> Enum.map($FUN) + |> Enum.into($INTO) + fix: | + $E + |> Enum.into($INTO, $FUN end) + metadata: + references: + - https://github.com/rrrene/credo/blob/master/lib/credo/check/refactor/map_into.ex + category: best-practice + technology: + - elixir +- id: elixir.lang.best-practice.enum-map-join.enum_map_join + message: >- + Using `Enum.map_join/3` is more efficient than using `Enum.map/2 |> Enum.join/2`. + severity: WARNING + languages: + - elixir + pattern-either: + - pattern: | + Enum.join(Enum.map($E, $FUN), $JOINER) + - pattern: | + Enum.map($E, $FUN) + |> Enum.join($JOINER) + - pattern: | + $E + |> Enum.map($FUN) + |> Enum.join($JOINER) + fix: | + $E + |> Enum.map_join($JOINER, $FUN end) + metadata: + references: + - https://github.com/rrrene/credo/blob/master/lib/credo/check/refactor/map_join.ex + category: best-practice + technology: + - elixir +- id: elixir.lang.correctness.atom-exhaustion.atom_exhaustion + message: >- + Atom values are appended to a global table but never removed. If input is user-controlled, dynamic instantiations such as `String.to_atom` or `List.to_atom` can lead to possible memory leaks. Instead, use `String.to_existing_atom` or `List.to_existing_atom`. + severity: ERROR + languages: + - elixir + patterns: + - pattern: $MODULE.to_atom($STRING) + - metavariable-regex: + metavariable: $MODULE + regex: ^(String|List)$ + fix: $MODULE.to_existing_atom($STRING) + metadata: + references: + - https://erlef.github.io/security-wg/secure_coding_and_deployment_hardening/atom_exhaustion.html + category: correctness + technology: + - elixir +- id: generic.dockerfile.best-practice.missing-yum-clean-all.missing-yum-clean-all + severity: WARNING + languages: [generic] + patterns: + - pattern: yum $COMMAND + - pattern-not-inside: RUN ... && yum clean all + - pattern-not-inside: RUN ... && \ yum clean all + message: >- + This yum command does not end with '&& yum clean all'. Running 'yum clean all' will remove cached + data and reduce package size. (This must be performed in the same RUN step.) + metadata: + source-rule-url: https://github.com/hadolint/hadolint/wiki/DL3032 + references: + - https://github.com/hadolint/hadolint/wiki/DL3032 + category: best-practice + technology: + - dockerfile + paths: + include: + - '*dockerfile*' + - '*Dockerfile*' +- id: generic.dockerfile.best-practice.use-absolute-workdir.use-absolute-workdir + pattern-either: + - patterns: + - pattern: WORKDIR $VALUE + - metavariable-pattern: + metavariable: $VALUE + patterns: + - pattern-not-regex: (\/.*) + - patterns: + - pattern: ENV $VAR=$VALUE ... $CMD ${$VAR} + - metavariable-pattern: + metavariable: $VALUE + patterns: + - pattern-not-regex: (\/.*) + - metavariable-pattern: + metavariable: $CMD + pattern: WORKDIR + - focus-metavariable: $CMD + message: >- + Detected a relative WORKDIR. Use absolute paths. This prevents + issues based on assumptions about the WORKDIR of previous containers. + severity: WARNING + languages: [generic] + metadata: + source-rule-url: https://github.com/hadolint/hadolint/wiki/DL3000 + references: + - https://github.com/hadolint/hadolint/wiki/DL3000 + category: best-practice + technology: + - dockerfile + paths: + include: + - '*dockerfile*' + - '*Dockerfile*' +- id: generic.dockerfile.correctness.alias-must-be-unique.alias-must-be-unique + severity: ERROR + languages: [generic] + patterns: + - pattern-either: + - pattern: | + FROM ... as $REF + ... + ... + FROM ... as $REF + - pattern: | + FROM ... AS $REF + ... + ... + FROM ... AS $REF + - pattern-not-inside: | + FROM ... as $REF + ... + ... + FROM ... as $REF- + - pattern-not-inside: | + FROM ... AS $REF + ... + ... + FROM ... AS $REF- + paths: + include: + - '*dockerfile*' + - '*Dockerfile*' + message: >- + Image aliases must have a unique name, and '$REF' is used twice. + Use another name for '$REF'. + metadata: + source-rule-url: https://github.com/hadolint/hadolint/wiki/DL3024 + references: + - https://github.com/hadolint/hadolint/wiki/DL3024 + category: correctness + technology: + - dockerfile +- id: generic.dockerfile.correctness.copy-from-own-alias.copy-from-own-alias + severity: ERROR + languages: [generic] + message: >- + COPY instructions cannot copy from its own alias. The '$REF' alias is used before + switching + to a new image. If you meant to switch to a new image, include + a new 'FROM' statement. Otherwise, remove the '--from=$REF' from the COPY statement. + metadata: + source-rule-url: https://github.com/hadolint/hadolint/wiki/DL3023 + references: + - https://github.com/hadolint/hadolint/wiki/DL3023 + category: correctness + technology: + - dockerfile + paths: + include: + - '*dockerfile*' + - '*Dockerfile*' + pattern-either: + - pattern: | + FROM $IMAGE:$TAG as $REF + ... + COPY --from=$REF + ... + FROM + - pattern: | + FROM $IMAGE:$TAG AS $REF + ... + COPY --from=$REF + ... + FROM +- id: generic.dockerfile.correctness.multiple-cmd-instructions.multiple-cmd-instructions + patterns: + - pattern-either: + - pattern: | + CMD ... + ... + CMD ... + - pattern: | + CMD [...] + ... + CMD [...] + - pattern: | + CMD [...] + ... + CMD ... + - pattern: | + CMD ... + ... + CMD [...] + - pattern-not-inside: | + CMD ... + ... + FROM $IMAGE + ... + CMD ... + - pattern-not: | + HEALTHCHECK $CMD + ... + CMD ... + - pattern-not: | + HEALTHCHECK $CMD + ... + CMD [...] + - pattern-not: | + CMD ... + ... + HEALTHCHECK $CMD + - pattern-not: | + CMD [...] + ... + HEALTHCHECK $CMD + message: Multiple CMD instructions were found. Only the last one will take effect. + languages: [dockerfile] + severity: ERROR + metadata: + source-rule-url: https://github.com/hadolint/hadolint/wiki/DL4003 + references: + - https://github.com/hadolint/hadolint/wiki/DL4003 + - https://kapeli.com/cheat_sheets/Dockerfile.docset/Contents/Resources/Documents/index#//dash_ref_Instructions/Entry/CMD/0 + category: correctness + technology: + - dockerfile + +- id: generic.dockerfile.missing-zypper-no-confirm-switch.missing-zypper-no-confirm-switch + severity: WARNING + languages: [dockerfile] + patterns: + - pattern: | + RUN ... zypper install ... + - pattern-not: | + RUN ... zypper install ... -y ... + - pattern-not: | + RUN ... zypper install ... --no-confirm ... + message: >- + This 'zypper install' is missing the '-y' switch. This might stall + builds because it requires human intervention. Add the '-y' switch. + metadata: + source-rule-url: https://github.com/hadolint/hadolint/wiki/DL3034 + references: + - https://github.com/hadolint/hadolint/wiki/DL3034 + category: best-practice + technology: + - dockerfile + paths: + include: + - '*dockerfile*' + - '*Dockerfile*' +- id: generic.secrets.gitleaks.adafruit-api-key.adafruit-api-key + message: A gitleaks adafruit-api-key was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:adafruit)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([a-z0-9_-]{32})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.adobe-client-id.adobe-client-id + message: A gitleaks adobe-client-id was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:adobe)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([a-f0-9]{32})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.adobe-client-secret.adobe-client-secret + message: A gitleaks adobe-client-secret was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)\b((p8e-)(?i)[a-z0-9]{32})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.age-secret-key.age-secret-key + message: A gitleaks age-secret-key was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: AGE-SECRET-KEY-1[QPZRY9X8GF2TVDW0S3JN54KHCE6MUA7L]{58} +- id: generic.secrets.gitleaks.airtable-api-key.airtable-api-key + message: A gitleaks airtable-api-key was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:airtable)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{17})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.algolia-api-key.algolia-api-key + message: A gitleaks algolia-api-key was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:algolia)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{32})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.alibaba-access-key-id.alibaba-access-key-id + message: A gitleaks alibaba-access-key-id was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)\b((LTAI)(?i)[a-z0-9]{20})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.alibaba-secret-key.alibaba-secret-key + message: A gitleaks alibaba-secret-key was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:alibaba)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{30})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.asana-client-id.asana-client-id + message: A gitleaks asana-client-id was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:asana)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([0-9]{16})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.asana-client-secret.asana-client-secret + message: A gitleaks asana-client-secret was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:asana)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{32})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.atlassian-api-token.atlassian-api-token + message: A gitleaks atlassian-api-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:atlassian|confluence|jira)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{24})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.authress-service-client-access-key.authress-service-client-access-key + message: A gitleaks authress-service-client-access-key was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)\b((?:sc|ext|scauth|authress)_[a-z0-9]{5,30}\.[a-z0-9]{4,6}\.acc[_-][a-z0-9-]{10,32}\.[a-z0-9+/_=-]{30,120})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.aws-access-token.aws-access-token + message: A gitleaks aws-access-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?:A3T[A-Z0-9]|AKIA|ASIA|ABIA|ACCA)[A-Z0-9]{16} +- id: generic.secrets.gitleaks.beamer-api-token.beamer-api-token + message: A gitleaks beamer-api-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:beamer)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}(b_[a-z0-9=_\-]{44})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.bitbucket-client-id.bitbucket-client-id + message: A gitleaks bitbucket-client-id was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:bitbucket)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{32})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.bitbucket-client-secret.bitbucket-client-secret + message: A gitleaks bitbucket-client-secret was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:bitbucket)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([a-z0-9=_\-]{64})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.bittrex-access-key.bittrex-access-key + message: A gitleaks bittrex-access-key was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:bittrex)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{32})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.bittrex-secret-key.bittrex-secret-key + message: A gitleaks bittrex-secret-key was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:bittrex)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{32})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.clojars-api-token.clojars-api-token + message: A gitleaks clojars-api-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(CLOJARS_)[a-z0-9]{60} +- id: generic.secrets.gitleaks.cloudflare-api-key.cloudflare-api-key + message: A gitleaks cloudflare-api-key was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:cloudflare)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([a-z0-9_-]{40})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.cloudflare-global-api-key.cloudflare-global-api-key + message: A gitleaks cloudflare-global-api-key was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:cloudflare)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([a-f0-9]{37})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.cloudflare-origin-ca-key.cloudflare-origin-ca-key + message: A gitleaks cloudflare-origin-ca-key was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: \b(v1\.0-[a-f0-9]{24}-[a-f0-9]{146})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.codecov-access-token.codecov-access-token + message: A gitleaks codecov-access-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:codecov)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{32})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.coinbase-access-token.coinbase-access-token + message: A gitleaks coinbase-access-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:coinbase)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([a-z0-9_-]{64})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.confluent-access-token.confluent-access-token + message: A gitleaks confluent-access-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:confluent)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{16})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.confluent-secret-key.confluent-secret-key + message: A gitleaks confluent-secret-key was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:confluent)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{64})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.contentful-delivery-api-token.contentful-delivery-api-token + message: A gitleaks contentful-delivery-api-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:contentful)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([a-z0-9=_\-]{43})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.databricks-api-token.databricks-api-token + message: A gitleaks databricks-api-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)\b(dapi[a-h0-9]{32})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.datadog-access-token.datadog-access-token + message: A gitleaks datadog-access-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:datadog)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{40})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.defined-networking-api-token.defined-networking-api-token + message: A gitleaks defined-networking-api-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:dnkey)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}(dnkey-[a-z0-9=_\-]{26}-[a-z0-9=_\-]{52})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.digitalocean-access-token.digitalocean-access-token + message: A gitleaks digitalocean-access-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)\b(doo_v1_[a-f0-9]{64})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.digitalocean-pat.digitalocean-pat + message: A gitleaks digitalocean-pat was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)\b(dop_v1_[a-f0-9]{64})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.digitalocean-refresh-token.digitalocean-refresh-token + message: A gitleaks digitalocean-refresh-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)\b(dor_v1_[a-f0-9]{64})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.discord-api-token.discord-api-token + message: A gitleaks discord-api-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:discord)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([a-f0-9]{64})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.discord-client-id.discord-client-id + message: A gitleaks discord-client-id was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:discord)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([0-9]{18})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.discord-client-secret.discord-client-secret + message: A gitleaks discord-client-secret was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:discord)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([a-z0-9=_\-]{32})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.doppler-api-token.doppler-api-token + message: A gitleaks doppler-api-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (dp\.pt\.)(?i)[a-z0-9]{43} +- id: generic.secrets.gitleaks.droneci-access-token.droneci-access-token + message: A gitleaks droneci-access-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:droneci)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{32})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.dropbox-api-token.dropbox-api-token + message: A gitleaks dropbox-api-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:dropbox)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{15})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.dropbox-long-lived-api-token.dropbox-long-lived-api-token + message: A gitleaks dropbox-long-lived-api-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:dropbox)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{11}(AAAAAAAAAA)[a-z0-9\-_=]{43})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.dropbox-short-lived-api-token.dropbox-short-lived-api-token + message: A gitleaks dropbox-short-lived-api-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:dropbox)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}(sl\.[a-z0-9\-=_]{135})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.duffel-api-token.duffel-api-token + message: A gitleaks duffel-api-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: duffel_(test|live)_(?i)[a-z0-9_\-=]{43} +- id: generic.secrets.gitleaks.dynatrace-api-token.dynatrace-api-token + message: A gitleaks dynatrace-api-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: dt0c01\.(?i)[a-z0-9]{24}\.[a-z0-9]{64} +- id: generic.secrets.gitleaks.easypost-api-token.easypost-api-token + message: A gitleaks easypost-api-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: \bEZAK(?i)[a-z0-9]{54} +- id: generic.secrets.gitleaks.easypost-test-api-token.easypost-test-api-token + message: A gitleaks easypost-test-api-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: \bEZTK(?i)[a-z0-9]{54} +- id: generic.secrets.gitleaks.etsy-access-token.etsy-access-token + message: A gitleaks etsy-access-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:etsy)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{24})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.facebook-access-token.facebook-access-token + message: A gitleaks facebook-access-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)\b(\d{15,16}(\||%)[0-9a-z\-_]{27,40})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.facebook-page-access-token.facebook-page-access-token + message: A gitleaks facebook-page-access-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)\b(EAA[MC][a-z0-9]{20,})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.facebook-secret.facebook-secret + message: A gitleaks facebook-secret was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:facebook)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([a-f0-9]{32})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.facebook.facebook + message: A gitleaks facebook was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:facebook)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([a-f0-9]{32})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.fastly-api-token.fastly-api-token + message: A gitleaks fastly-api-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:fastly)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([a-z0-9=_\-]{32})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.finicity-api-token.finicity-api-token + message: A gitleaks finicity-api-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:finicity)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([a-f0-9]{32})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.finicity-client-secret.finicity-client-secret + message: A gitleaks finicity-client-secret was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:finicity)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{20})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.finnhub-access-token.finnhub-access-token + message: A gitleaks finnhub-access-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:finnhub)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{20})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.flickr-access-token.flickr-access-token + message: A gitleaks flickr-access-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:flickr)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{32})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.flutterwave-encryption-key.flutterwave-encryption-key + message: A gitleaks flutterwave-encryption-key was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: FLWSECK_TEST-(?i)[a-h0-9]{12} +- id: generic.secrets.gitleaks.flutterwave-public-key.flutterwave-public-key + message: A gitleaks flutterwave-public-key was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: FLWPUBK_TEST-(?i)[a-h0-9]{32}-X +- id: generic.secrets.gitleaks.flutterwave-secret-key.flutterwave-secret-key + message: A gitleaks flutterwave-secret-key was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: FLWSECK_TEST-(?i)[a-h0-9]{32}-X +- id: generic.secrets.gitleaks.frameio-api-token.frameio-api-token + message: A gitleaks frameio-api-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: fio-u-(?i)[a-z0-9\-_=]{64} +- id: generic.secrets.gitleaks.freshbooks-access-token.freshbooks-access-token + message: A gitleaks freshbooks-access-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:freshbooks)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{64})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.gcp-api-key.gcp-api-key + message: A gitleaks gcp-api-key was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)\b(AIza[0-9A-Za-z\\-_]{35})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.generic-api-key.generic-api-key + message: >- + A gitleaks generic-api-key was detected which attempts to identify hard-coded credentials. + It is not recommended to store credentials in source-code, as this risks secrets being leaked + and used by either an internal or external malicious adversary. It is recommended to use + environment variables to securely provide credentials or retrieve credentials from a + secure vault or HSM (Hardware Security Module). This rule can introduce a lot of false positives, + it is not recommended to be used in PR comments. + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + paths: + exclude: + - "*.svg" + - "*go.sum" + - "*cargo.lock" + - "*package.json" + - "*package-lock.json" + - "*bundle.js" + - "*pnpm-lock*" + - "*Podfile.lock" + - "*/openssl/*.h" + - "*.xcscmblueprint" + patterns: + # The original regex from gitleaks is in this rule https://semgrep.dev/playground/s/57qk (but its very noisy) even with our entropy analyzer + # This will likely remove some true positives, but this rule is overly noisy + # Added (?-s) to prevent multi-lines with . which was causing a lot of FPs + # The only thing which has changed from the actual regex of gitleaks is adding in (?!([a-z]+\.[a-zA-Z]+)|.*(\d{4}-\d{2}-\d{2}|[a-z]+-[a-z]+.*)|:*(?!("|'))[0-9A-Za-z]+\.[0-9A-Za-z]+,|[A-Z]+_[A-Z]+_) + # We also added a capture group around the 'content' so we can + # added negative lookaheads to remove: + # [a-z]+\.[a-zA-Z]+ (this.valueValue) + # .* + # \d{4}-\d{2}-\d{2} (2017/03/12) + # [a-z]+-[a-z]+.*. abc123-abc123 + # :*(?!("|'))[0-9A-Za-z]+\.[0-9A-Za-z]+, : 0123.0312abc, + # [A-Z]+_[A-Z]+_ VALUE_VALUE_ + # Added ~ in the content as a value since a customer said it was missing a finding + - pattern-regex: (?i)(?:key|api|token|secret|client|passwd|password|auth|access)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|@\"|\"|\s|=|\x60){0,5}(?!([a-z]+\.[a-zA-Z]+)|.*(\d{4}-\d{2}-\d{2}|[a-z]+-[a-z]+.*)|:*(?!("|'))[0-9A-Za-z]+\.[0-9A-Za-z]+,|[A-Z]+_[A-Z]+_)(?P[0-9a-z\-_.=\~]{10,150})(?:['|\"|\n|\r|\s|\x60|;]|$) + - metavariable-analysis: + analyzer: entropy + metavariable: $CONTENT + - focus-metavariable: $CONTENT + # These remove values from the 'entire line so it could be the PublicKey=Something' could cause false negatives + - pattern-not-regex: .*((?i)omitted|arn:aws|(?i)(pub.*key|public.*key)|(?i)clientToken|symbol|cache|author\.).* + # These remove keywords or ip addresses from the content so only inside "PASSWORDEXAMPLE" its generic so anywhere 'inside' the $CONTENT + - pattern-not-regex: (\d\.\d\.\d-}|([\d]{1,3}\.[\d]{1,3}\.[\d]{1,3}\.[\d]{1,3})|(\w)\1{5}|(?i)keywords|xxxx|eeeeeeee|0000|\*\*\*|example|test|author=|author("|')|preview|[A-Z]+_KEY|[.]value|[.]key|-\d\.\d\.) + # These are start or end checks e.g. starts as a hex code, ends with .json or starts with abcd or 12345 which usually indicates example code. + - metavariable-regex: + metavariable: $CONTENT + regex: (?!(^0x0*|^pub)|.*\.(bin|json|exe)$|.*(?i)(Client|Factory)$|(^__[A-Za-z]+__$)|^(12345|abcd)|^\d+(\.\d+)?$) + # Remove AAAAA, BBBBB, CCCCC, and ..... + - pattern-not-regex: (\w|\.)\1{5} + # stopwords from https://github.com/gitleaks/gitleaks/blob/d9f86d6123d9ef2558c4852a522a7a071d6a6fe9/cmd/generate/config/rules/stopwords.go#L4 + - metavariable-regex: + metavariable: $CONTENT + regex: (?!(?i).*(client|endpoint|vpn|_ec2_|aws_|authorize|author|define|config|credential|setting|sample|xxxxxx|000000|buffer|delete|aaaaaa|fewfwef|getenv|env_|system|example|ecdsa|sha256|sha1|sha2|md5|alert|wizard|target|onboard|welcome|page|exploit|experiment|expire|rabbitmq|scraper|widget|music|dns_|dns-|yahoo|want|json|action|script|fix_|fix-|develop|compas|stripe|service|master|metric|tech|gitignore|rich|open|stack|irc_|irc-|sublime|kohana|has_|has-|fabric|wordpres|role|osx_|osx-|boost|addres|queue|working|sandbox|internet|print|vision|tracking|being|generator|traffic|world|pull|rust|watcher|small|auth|full|hash|more|install|auto|complete|learn|paper|installer|research|acces|last|binding|spine|into|chat|algorithm|resource|uploader|video|maker|next|proc|lock|robot|snake|patch|matrix|drill|terminal|term|stuff|genetic|generic|identity|audit|pattern|audio|web_|web-|crud|problem|statu|cms-|cms_|arch|coffee|workflow|changelog|another|uiview|content|kitchen|gnu_|gnu-|gnu\.|conf|couchdb|client|opencv|rendering|update|concept|varnish|gui_|gui-|gui\.|version|shared|extra|product|still|not_|not-|not\.|drop|ring|png_|png-|png\.|actively|import|output|backup|start|embedded|registry|pool|semantic|instagram|bash|system|ninja|drupal|jquery|polyfill|physic|league|guide|pack|synopsi|sketch|injection|svg_|svg-|svg\.|friendly|wave|convert|manage|camera|link|slide|timer|wrapper|gallery|url_|url-|url\.|todomvc|requirej|party|http|payment|async|library|home|coco|gaia|display|universal|func|metadata|hipchat|under|room|config|personal|realtime|resume|database|testing|tiny|basic|forum|meetup|yet_|yet-|yet\.|cento|dead|fluentd|editor|utilitie|run_|run-|run\.|box_|box-|box\.|bot_|bot-|bot\.|making|sample|group|monitor|ajax|parallel|cassandra|ultimate|site|get_|get-|get\.|gen_|gen-|gen\.|gem_|gem-|gem\.|extended|image|knife|asset|nested|zero|plugin|bracket|mule|mozilla|number|act_|act-|act\.|map_|map-|map\.|micro|debug|openshift|chart|expres|backend|task|source|translate|jbos|composer|sqlite|profile|mustache|mqtt|yeoman|have|builder|smart|like|oauth|school|guideline|captcha|filter|bitcoin|bridge|color|toolbox|discovery|new_|new-|new\.|dashboard|when|setting|level|post|standard|port|platform|yui_|yui-|yui\.|grunt|animation|haskell|icon|latex|cheat|lua_|lua-|lua\.|gulp|case|author|without|simulator|wifi|directory|lisp|list|flat|adventure|story|storm|gpu_|gpu-|gpu\.|store|caching|attention|solr|logger|demo|shortener|hadoop|finder|phone|pipeline|range|textmate|showcase|app_|app-|app\.|idiomatic|edit|our_|our-|our\.|out_|out-|out\.|sentiment|linked|why_|why-|why\.|local|cube|gmail|job_|job-|job\.|rpc_|rpc-|rpc\.|contest|tcp_|tcp-|tcp\.|usage|buildout|weather|transfer|automated|sphinx|issue|sas_|sas-|sas\.|parallax|jasmine|addon|machine|solution|dsl_|dsl-|dsl\.|episode|menu|theme|best|adapter|debugger|chrome|tutorial|life|step|people|joomla|paypal|developer|solver|team|current|love|visual|date|data|canva|container|future|xml_|xml-|xml\.|twig|nagio|spatial|original|sync|archived|refinery|science|mapping|gitlab|play|ext_|ext-|ext\.|session|impact|set_|set-|set\.|see_|see-|see\.|migration|commit|community|shopify|what'|cucumber|statamic|mysql|location|tower|line|code|amqp|hello|send|index|high|notebook|alloy|python|field|document|soap|edition|email|php_|php-|php\.|command|transport|official|upload|study|secure|angularj|akka|scalable|package|request|con_|con-|con\.|flexible|security|comment|module|flask|graph|flash|apache|change|window|space|lambda|sheet|bookmark|carousel|friend|objective|jekyll|bootstrap|first|article|gwt_|gwt-|gwt\.|classic|media|websocket|touch|desktop|real|read|recorder|moved|storage|validator|add-on|pusher|scs_|scs-|scs\.|inline|asp_|asp-|asp\.|timeline|base|encoding|ffmpeg|kindle|tinymce|pretty|jpa_|jpa-|jpa\.|used|user|required|webhook|download|resque|espresso|cloud|mongo|benchmark|pure|cakephp|modx|mode|reactive|fuel|written|flickr|mail|brunch|meteor|dynamic|neo_|neo-|neo\.|new_|new-|new\.|net_|net-|net\.|typo|type|keyboard|erlang|adobe|logging|ckeditor|message|iso_|iso-|iso\.|hook|ldap|folder|reference|railscast|www_|www-|www\.|tracker|azure|fork|form|digital|exporter|skin|string|template|designer|gollum|fluent|entity|language|alfred|summary|wiki|kernel|calendar|plupload|symfony|foundry|remote|talk|search|dev_|dev-|dev\.|del_|del-|del\.|token|idea|sencha|selector|interface|create|fun_|fun-|fun\.|groovy|query|grail|red_|red-|red\.|laravel|monkey|slack|supported|instant|value|center|latest|work|but_|but-|but\.|bug_|bug-|bug\.|virtual|tweet|statsd|studio|path|real-time|frontend|notifier|coding|tool|firmware|flow|random|mediawiki|bosh|been|beer|lightbox|theory|origin|redmine|hub_|hub-|hub\.|require|pro_|pro-|pro\.|ant_|ant-|ant\.|any_|any-|any\.|recipe|closure|mapper|event|todo|model|redi|provider|rvm_|rvm-|rvm\.|program|memcached|rail|silex|foreman|activity|license|strategy|batch|streaming|fast|use_|use-|use\.|usb_|usb-|usb\.|impres|academy|slider|please|layer|cros|now_|now-|now\.|miner|extension|own_|own-|own\.|app_|app-|app\.|debian|symphony|example|feature|serie|tree|project|runner|entry|leetcode|layout|webrtc|logic|login|worker|toolkit|mocha|support|back|inside|device|jenkin|contact|fake|awesome|ocaml|bit_|bit-|bit\.|drive|screen|prototype|gist|binary|nosql|rest|overview|dart|dark|emac|mongoid|solarized|homepage|emulator|commander|django|yandex|gradle|xcode|writer|crm_|crm-|crm\.|jade|startup|error|using|format|name|spring|parser|scratch|magic|try_|try-|try\.|rack|directive|challenge|slim|counter|element|chosen|doc_|doc-|doc\.|meta|should|button|packet|stream|hardware|android|infinite|password|software|ghost|xamarin|spec|chef|interview|hubot|mvc_|mvc-|mvc\.|exercise|leaflet|launcher|air_|air-|air\.|photo|board|boxen|way_|way-|way\.|computing|welcome|notepad|portfolio|cat_|cat-|cat\.|can_|can-|can\.|magento|yaml|domain|card|yii_|yii-|yii\.|checker|browser|upgrade|only|progres|aura|ruby_|ruby-|ruby\.|polymer|util|lite|hackathon|rule|log_|log-|log\.|opengl|stanford|skeleton|history|inspector|help|soon|selenium|lab_|lab-|lab\.|scheme|schema|look|ready|leveldb|docker|game|minimal|logstash|messaging|within|heroku|mongodb|kata|suite|picker|win_|win-|win\.|wip_|wip-|wip\.|panel|started|starter|front-end|detector|deploy|editing|based|admin|capture|spree|page|bundle|goal|rpg_|rpg-|rpg\.|setup|side|mean|reader|cookbook|mini|modern|seed|dom_|dom-|dom\.|doc_|doc-|doc\.|dot_|dot-|dot\.|syntax|sugar|loader|website|make|kit_|kit-|kit\.|protocol|human|daemon|golang|manager|countdown|connector|swagger|map_|map-|map\.|mac_|mac-|mac\.|man_|man-|man\.|orm_|orm-|orm\.|org_|org-|org\.|little|zsh_|zsh-|zsh\.|shop|show|workshop|money|grid|server|octopres|svn_|svn-|svn\.|ember|embed|general|file|important|dropbox|portable|public|docpad|fish|sbt_|sbt-|sbt\.|done|para|network|common|readme|popup|simple|purpose|mirror|single|cordova|exchange|object|design|gateway|account|lamp|intellij|math|mit_|mit-|mit\.|control|enhanced|emitter|multi|add_|add-|add\.|about|socket|preview|vagrant|cli_|cli-|cli\.|powerful|top_|top-|top\.|radio|watch|fluid|amazon|report|couchbase|automatic|detection|sprite|pyramid|portal|advanced|plu_|plu-|plu\.|runtime|git_|git-|git\.|uri_|uri-|uri\.|haml|node|sql_|sql-|sql\.|cool|core|obsolete|handler|iphone|extractor|array|copy|nlp_|nlp-|nlp\.|reveal|pop_|pop-|pop\.|engine|parse|check|html|nest|all_|all-|all\.|chinese|buildpack|what|tag_|tag-|tag\.|proxy|style|cookie|feed|restful|compiler|creating|prelude|context|java|rspec|mock|backbone|light|spotify|flex|related|shell|which|clas|webapp|swift|ansible|unity|console|tumblr|export|campfire|conway'|made|riak|hero|here|unix|unit|glas|smtp|how_|how-|how\.|hot_|hot-|hot\.|debug|release|diff|player|easy|right|old_|old-|old\.|animate|time|push|explorer|course|training|nette|router|draft|structure|note|salt|where|spark|trello|power|method|social|via_|via-|via\.|vim_|vim-|vim\.|select|webkit|github|ftp_|ftp-|ftp\.|creator|mongoose|led_|led-|led\.|movie|currently|pdf_|pdf-|pdf\.|load|markdown|phalcon|input|custom|atom|oracle|phonegap|ubuntu|great|rdf_|rdf-|rdf\.|popcorn|firefox|zip_|zip-|zip\.|cuda|dotfile|static|openwrt|viewer|powered|graphic|les_|les-|les\.|doe_|doe-|doe\.|maven|word|eclipse|lab_|lab-|lab\.|hacking|steam|analytic|option|abstract|archive|reality|switcher|club|write|kafka|arduino|angular|online|title|don't|contao|notice|analyzer|learning|zend|external|staging|busines|tdd_|tdd-|tdd\.|scanner|building|snippet|modular|bower|stm_|stm-|stm\.|lib_|lib-|lib\.|alpha|mobile|clean|linux|nginx|manifest|some|raspberry|gnome|ide_|ide-|ide\.|block|statistic|info|drag|youtube|koan|facebook|paperclip|art_|art-|art\.|quality|tab_|tab-|tab\.|need|dojo|shield|computer|stat|state|twitter|utility|converter|hosting|devise|liferay|updated|force|tip_|tip-|tip\.|behavior|active|call|answer|deck|better|principle|ches|bar_|bar-|bar\.|reddit|three|haxe|just|plug-in|agile|manual|tetri|super|beta|parsing|doctrine|minecraft|useful|perl|sharing|agent|switch|view|dash|channel|repo|pebble|profiler|warning|cluster|running|markup|evented|mod_|mod-|mod\.|share|csv_|csv-|csv\.|response|good|house|connect|built|build|find|ipython|webgl|big_|big-|big\.|google|scala|sdl_|sdl-|sdl\.|sdk_|sdk-|sdk\.|native|day_|day-|day\.|puppet|text|routing|helper|linkedin|crawler|host|guard|merchant|poker|over|writing|free|classe|component|craft|nodej|phoenix|longer|quick|lazy|memory|clone|hacker|middleman|factory|motion|multiple|tornado|hack|ssh_|ssh-|ssh\.|review|vimrc|driver|driven|blog|particle|table|intro|importer|thrift|xmpp|framework|refresh|react|font|librarie|variou|formatter|analysi|karma|scroll|tut_|tut-|tut\.|apple|tag_|tag-|tag\.|tab_|tab-|tab\.|category|ionic|cache|homebrew|reverse|english|getting|shipping|clojure|boot|book|branch|combination|combo)) +- id: generic.secrets.gitleaks.github-app-token.github-app-token + message: A gitleaks github-app-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (ghu|ghs)_[0-9a-zA-Z]{36} +- id: generic.secrets.gitleaks.github-fine-grained-pat.github-fine-grained-pat + message: A gitleaks github-fine-grained-pat was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: github_pat_[0-9a-zA-Z_]{82} +- id: generic.secrets.gitleaks.github-oauth.github-oauth + message: A gitleaks github-oauth was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: gho_[0-9a-zA-Z]{36} +- id: generic.secrets.gitleaks.github-pat.github-pat + message: A gitleaks github-pat was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: ghp_[0-9a-zA-Z]{36} +- id: generic.secrets.gitleaks.github-refresh-token.github-refresh-token + message: A gitleaks github-refresh-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: ghr_[0-9a-zA-Z]{36} +- id: generic.secrets.gitleaks.gitlab-pat.gitlab-pat + message: A gitleaks gitlab-pat was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: glpat-[0-9a-zA-Z\-\_]{20} +- id: generic.secrets.gitleaks.gitlab-ptt.gitlab-ptt + message: A gitleaks gitlab-ptt was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: glptt-[0-9a-f]{40} +- id: generic.secrets.gitleaks.gitlab-rrt.gitlab-rrt + message: A gitleaks gitlab-rrt was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: GR1348941[0-9a-zA-Z\-\_]{20} +- id: generic.secrets.gitleaks.gitter-access-token.gitter-access-token + message: A gitleaks gitter-access-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:gitter)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([a-z0-9_-]{40})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.gocardless-api-token.gocardless-api-token + message: A gitleaks gocardless-api-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:gocardless)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}(live_(?i)[a-z0-9\-_=]{40})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.grafana-api-key.grafana-api-key + message: A gitleaks grafana-api-key was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)\b(eyJrIjoi[A-Za-z0-9]{70,400}={0,2})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.grafana-cloud-api-token.grafana-cloud-api-token + message: A gitleaks grafana-cloud-api-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)\b(glc_[A-Za-z0-9+/]{32,400}={0,2})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.grafana-service-account-token.grafana-service-account-token + message: A gitleaks grafana-service-account-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)\b(glsa_[A-Za-z0-9]{32}_[A-Fa-f0-9]{8})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.harness-api-key.harness-api-key + message: A gitleaks harness-api-key was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: ((?:pat|sat)\.[a-zA-Z0-9]{22}\.[a-zA-Z0-9]{24}\.[a-zA-Z0-9]{20}) +- id: generic.secrets.gitleaks.hashicorp-tf-api-token.hashicorp-tf-api-token + message: A gitleaks hashicorp-tf-api-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)[a-z0-9]{14}\.atlasv1\.[a-z0-9\-_=]{60,70} +- id: generic.secrets.gitleaks.hashicorp-tf-password.hashicorp-tf-password + message: A gitleaks hashicorp-tf-password was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:administrator_login_password|password)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}("[a-z0-9=_\-]{8,20}")(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.heroku-api-key.heroku-api-key + message: A gitleaks heroku-api-key was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:heroku)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.hubspot-api-key.hubspot-api-key + message: A gitleaks hubspot-api-key was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:hubspot)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.huggingface-access-token.huggingface-access-token + message: A gitleaks huggingface-access-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?:^|[\\'"` >=:])(hf_[a-zA-Z]{34})(?:$|[\\'"` <]) +- id: generic.secrets.gitleaks.huggingface-organization-api-token.huggingface-organization-api-token + message: A gitleaks huggingface-organization-api-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?:^|[\\'"` >=:\(,)])(api_org_[a-zA-Z]{34})(?:$|[\\'"` <\),]) +- id: generic.secrets.gitleaks.infracost-api-token.infracost-api-token + message: A gitleaks infracost-api-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)\b(ico-[a-zA-Z0-9]{32})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.intercom-api-key.intercom-api-key + message: A gitleaks intercom-api-key was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:intercom)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([a-z0-9=_\-]{60})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.intra42-client-secret.intra42-client-secret + message: A gitleaks intra42-client-secret was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)\b(s-s4t2(?:ud|af)-[abcdef0123456789]{64})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.jfrog-api-key.jfrog-api-key + message: A gitleaks jfrog-api-key was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:jfrog|artifactory|bintray|xray)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{73})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.jfrog-identity-token.jfrog-identity-token + message: A gitleaks jfrog-identity-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:jfrog|artifactory|bintray|xray)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{64})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.jwt-base64.jwt-base64 + message: A gitleaks jwt-base64 was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: \bZXlK(?:(?PaGJHY2lPaU)|(?PaGNIVWlPaU)|(?PaGNIWWlPaU)|(?PaGRXUWlPaU)|(?PaU5qUWlP)|(?PamNtbDBJanBi)|(?PamRIa2lPaU)|(?PbGNHc2lPbn)|(?PbGJtTWlPaU)|(?PcWEzVWlPaU)|(?PcWQyc2lPb)|(?PcGMzTWlPaU)|(?PcGRpSTZJ)|(?PcmFXUWlP)|(?PclpYbGZiM0J6SWpwY)|(?PcmRIa2lPaUp)|(?PdWIyNWpaU0k2)|(?Pd01tTWlP)|(?Pd01uTWlPaU)|(?Pd2NIUWlPaU)|(?PemRXSWlPaU)|(?PemRuUWlP)|(?PMFlXY2lPaU)|(?PMGVYQWlPaUp)|(?PMWNtd2l)|(?PMWMyVWlPaUp)|(?PMlpYSWlPaU)|(?PMlpYSnphVzl1SWpv)|(?PNElqb2)|(?PNE5XTWlP)|(?PNE5YUWlPaU)|(?PNE5YUWpVekkxTmlJNkl)|(?PNE5YVWlPaU)|(?PNmFYQWlPaU))[a-zA-Z0-9\/\\_+\-\r\n]{40,}={0,2} +- id: generic.secrets.gitleaks.jwt.jwt + message: A gitleaks jwt was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: \b(ey[a-zA-Z0-9]{17,}\.ey[a-zA-Z0-9\/\\_-]{17,}\.(?:[a-zA-Z0-9\/\\_-]{10,}={0,2})?)(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.kraken-access-token.kraken-access-token + message: A gitleaks kraken-access-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:kraken)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([a-z0-9\/=_\+\-]{80,90})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.kucoin-access-token.kucoin-access-token + message: A gitleaks kucoin-access-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:kucoin)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([a-f0-9]{24})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.kucoin-secret-key.kucoin-secret-key + message: A gitleaks kucoin-secret-key was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:kucoin)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.launchdarkly-access-token.launchdarkly-access-token + message: A gitleaks launchdarkly-access-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:launchdarkly)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([a-z0-9=_\-]{40})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.linear-api-key.linear-api-key + message: A gitleaks linear-api-key was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: lin_api_(?i)[a-z0-9]{40} +- id: generic.secrets.gitleaks.linear-client-secret.linear-client-secret + message: A gitleaks linear-client-secret was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:linear)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([a-f0-9]{32})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.linkedin-client-id.linkedin-client-id + message: A gitleaks linkedin-client-id was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:linkedin|linked-in)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{14})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.linkedin-client-secret.linkedin-client-secret + message: A gitleaks linkedin-client-secret was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:linkedin|linked-in)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{16})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.lob-api-key.lob-api-key + message: A gitleaks lob-api-key was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:lob)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}((live|test)_[a-f0-9]{35})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.lob-pub-api-key.lob-pub-api-key + message: A gitleaks lob-pub-api-key was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:lob)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}((test|live)_pub_[a-f0-9]{31})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.mailchimp-api-key.mailchimp-api-key + message: A gitleaks mailchimp-api-key was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:MailchimpSDK.initialize|mailchimp)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([a-f0-9]{32}-us\d\d)(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.mailgun-private-api-token.mailgun-private-api-token + message: A gitleaks mailgun-private-api-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:mailgun)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}(key-[a-f0-9]{32})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.mailgun-pub-key.mailgun-pub-key + message: A gitleaks mailgun-pub-key was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:mailgun)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}(pubkey-[a-f0-9]{32})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.mailgun-signing-key.mailgun-signing-key + message: A gitleaks mailgun-signing-key was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:mailgun)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([a-h0-9]{32}-[a-h0-9]{8}-[a-h0-9]{8})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.mapbox-api-token.mapbox-api-token + message: A gitleaks mapbox-api-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:mapbox)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}(pk\.[a-z0-9]{60}\.[a-z0-9]{22})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.mattermost-access-token.mattermost-access-token + message: A gitleaks mattermost-access-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:mattermost)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{26})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.messagebird-api-token.messagebird-api-token + message: A gitleaks messagebird-api-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:messagebird|message-bird|message_bird)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{25})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.messagebird-client-id.messagebird-client-id + message: A gitleaks messagebird-client-id was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:messagebird|message-bird|message_bird)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.microsoft-teams-webhook.microsoft-teams-webhook + message: A gitleaks microsoft-teams-webhook was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: https:\/\/[a-z0-9]+\.webhook\.office\.com\/webhookb2\/[a-z0-9]{8}-([a-z0-9]{4}-){3}[a-z0-9]{12}@[a-z0-9]{8}-([a-z0-9]{4}-){3}[a-z0-9]{12}\/IncomingWebhook\/[a-z0-9]{32}\/[a-z0-9]{8}-([a-z0-9]{4}-){3}[a-z0-9]{12} +- id: generic.secrets.gitleaks.netlify-access-token.netlify-access-token + message: A gitleaks netlify-access-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:netlify)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([a-z0-9=_\-]{40,46})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.new-relic-browser-api-token.new-relic-browser-api-token + message: A gitleaks new-relic-browser-api-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:new-relic|newrelic|new_relic)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}(NRJS-[a-f0-9]{19})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.new-relic-insert-key.new-relic-insert-key + message: A gitleaks new-relic-insert-key was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:new-relic|newrelic|new_relic)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}(NRII-[a-z0-9-]{32})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.new-relic-user-api-id.new-relic-user-api-id + message: A gitleaks new-relic-user-api-id was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:new-relic|newrelic|new_relic)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{64})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.new-relic-user-api-key.new-relic-user-api-key + message: A gitleaks new-relic-user-api-key was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:new-relic|newrelic|new_relic)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}(NRAK-[a-z0-9]{27})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.npm-access-token.npm-access-token + message: A gitleaks npm-access-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)\b(npm_[a-z0-9]{36})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.nytimes-access-token.nytimes-access-token + message: A gitleaks nytimes-access-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:nytimes|new-york-times,|newyorktimes)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([a-z0-9=_\-]{32})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.okta-access-token.okta-access-token + message: A gitleaks okta-access-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:okta)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([a-z0-9=_\-]{42})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.openai-api-key.openai-api-key + message: A gitleaks openai-api-key was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)\b(sk-[a-zA-Z0-9]{20}T3BlbkFJ[a-zA-Z0-9]{20})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.plaid-api-token.plaid-api-token + message: A gitleaks plaid-api-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:plaid)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}(access-(?:sandbox|development|production)-[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.plaid-client-id.plaid-client-id + message: A gitleaks plaid-client-id was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:plaid)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{24})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.plaid-secret-key.plaid-secret-key + message: A gitleaks plaid-secret-key was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:plaid)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{30})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.planetscale-api-token.planetscale-api-token + message: A gitleaks planetscale-api-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)\b(pscale_tkn_(?i)[a-z0-9=\-_\.]{32,64})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.planetscale-oauth-token.planetscale-oauth-token + message: A gitleaks planetscale-oauth-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)\b(pscale_oauth_(?i)[a-z0-9=\-_\.]{32,64})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.planetscale-password.planetscale-password + message: A gitleaks planetscale-password was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)\b(pscale_pw_(?i)[a-z0-9=\-_\.]{32,64})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.postman-api-token.postman-api-token + message: A gitleaks postman-api-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)\b(PMAK-(?i)[a-f0-9]{24}\-[a-f0-9]{34})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.prefect-api-token.prefect-api-token + message: A gitleaks prefect-api-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)\b(pnu_[a-z0-9]{36})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.private-key.private-key + message: A gitleaks private-key was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)-----BEGIN[ A-Z0-9_-]{0,100}PRIVATE KEY( BLOCK)?-----[\s\S-]*KEY( BLOCK)?---- +- id: generic.secrets.gitleaks.pulumi-api-token.pulumi-api-token + message: A gitleaks pulumi-api-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)\b(pul-[a-f0-9]{40})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.pypi-upload-token.pypi-upload-token + message: A gitleaks pypi-upload-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: pypi-AgEIcHlwaS5vcmc[A-Za-z0-9\-_]{50,1000} +- id: generic.secrets.gitleaks.rapidapi-access-token.rapidapi-access-token + message: A gitleaks rapidapi-access-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:rapidapi)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([a-z0-9_-]{50})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.readme-api-token.readme-api-token + message: A gitleaks readme-api-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)\b(rdme_[a-z0-9]{70})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.rubygems-api-token.rubygems-api-token + message: A gitleaks rubygems-api-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)\b(rubygems_[a-f0-9]{48})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.scalingo-api-token.scalingo-api-token + message: A gitleaks scalingo-api-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: \b(tk-us-[a-zA-Z0-9-_]{48})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.sendbird-access-id.sendbird-access-id + message: A gitleaks sendbird-access-id was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:sendbird)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.sendbird-access-token.sendbird-access-token + message: A gitleaks sendbird-access-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:sendbird)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([a-f0-9]{40})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.sendgrid-api-token.sendgrid-api-token + message: A gitleaks sendgrid-api-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)\b(SG\.(?i)[a-z0-9=_\-\.]{66})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.sendinblue-api-token.sendinblue-api-token + message: A gitleaks sendinblue-api-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)\b(xkeysib-[a-f0-9]{64}\-(?i)[a-z0-9]{16})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.sentry-access-token.sentry-access-token + message: A gitleaks sentry-access-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:sentry)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([a-f0-9]{64})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.shippo-api-token.shippo-api-token + message: A gitleaks shippo-api-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)\b(shippo_(live|test)_[a-f0-9]{40})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.shopify-access-token.shopify-access-token + message: A gitleaks shopify-access-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: shpat_[a-fA-F0-9]{32} +- id: generic.secrets.gitleaks.shopify-custom-access-token.shopify-custom-access-token + message: A gitleaks shopify-custom-access-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: shpca_[a-fA-F0-9]{32} +- id: generic.secrets.gitleaks.shopify-private-app-access-token.shopify-private-app-access-token + message: A gitleaks shopify-private-app-access-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: shppa_[a-fA-F0-9]{32} +- id: generic.secrets.gitleaks.shopify-shared-secret.shopify-shared-secret + message: A gitleaks shopify-shared-secret was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: shpss_[a-fA-F0-9]{32} +- id: generic.secrets.gitleaks.sidekiq-secret.sidekiq-secret + message: A gitleaks sidekiq-secret was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:BUNDLE_ENTERPRISE__CONTRIBSYS__COM|BUNDLE_GEMS__CONTRIBSYS__COM)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([a-f0-9]{8}:[a-f0-9]{8})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.sidekiq-sensitive-url.sidekiq-sensitive-url + message: A gitleaks sidekiq-sensitive-url was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)\b(http(?:s??):\/\/)([a-f0-9]{8}:[a-f0-9]{8})@(?:gems.contribsys.com|enterprise.contribsys.com)(?:[\/|\#|\?|:]|$) +- id: generic.secrets.gitleaks.slack-app-token.slack-app-token + message: A gitleaks slack-app-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(xapp-\d-[A-Z0-9]+-\d+-[a-z0-9]+) +- id: generic.secrets.gitleaks.slack-bot-token.slack-bot-token + message: A gitleaks slack-bot-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (xoxb-[0-9]{10,13}\-[0-9]{10,13}[a-zA-Z0-9-]*) +- id: generic.secrets.gitleaks.slack-config-access-token.slack-config-access-token + message: A gitleaks slack-config-access-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(xoxe.xox[bp]-\d-[A-Z0-9]{163,166}) +- id: generic.secrets.gitleaks.slack-config-refresh-token.slack-config-refresh-token + message: A gitleaks slack-config-refresh-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(xoxe-\d-[A-Z0-9]{146}) +- id: generic.secrets.gitleaks.slack-legacy-bot-token.slack-legacy-bot-token + message: A gitleaks slack-legacy-bot-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (xoxb-[0-9]{8,14}\-[a-zA-Z0-9]{18,26}) +- id: generic.secrets.gitleaks.slack-legacy-token.slack-legacy-token + message: A gitleaks slack-legacy-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (xox[os]-\d+-\d+-\d+-[a-fA-F\d]+) +- id: generic.secrets.gitleaks.slack-legacy-workspace-token.slack-legacy-workspace-token + message: A gitleaks slack-legacy-workspace-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (xox[ar]-(?:\d-)?[0-9a-zA-Z]{8,48}) +- id: generic.secrets.gitleaks.slack-user-token.slack-user-token + message: A gitleaks slack-user-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (xox[pe](?:-[0-9]{10,13}){3}-[a-zA-Z0-9-]{28,34}) +- id: generic.secrets.gitleaks.slack-webhook-url.slack-webhook-url + message: A gitleaks slack-webhook-url was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (https?:\/\/)?hooks.slack.com\/(services|workflows)\/[A-Za-z0-9+\/]{43,46} +- id: generic.secrets.gitleaks.snyk-api-token.snyk-api-token + message: A gitleaks snyk-api-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:snyk_token|snyk_key|snyk_api_token|snyk_api_key|snyk_oauth_token)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.square-access-token.square-access-token + message: A gitleaks square-access-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)\b((EAAA|sq0atp-)[0-9A-Za-z\-_]{22,60})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.squarespace-access-token.squarespace-access-token + message: A gitleaks squarespace-access-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:squarespace)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.stripe-access-token.stripe-access-token + message: A gitleaks stripe-access-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)\b((sk|rk)_(test|live|prod)_[0-9a-z]{10,99})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.sumologic-access-id.sumologic-access-id + message: A gitleaks sumologic-access-id was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i:(?:sumo)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3})(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}(su[a-zA-Z0-9]{12})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.sumologic-access-token.sumologic-access-token + message: A gitleaks sumologic-access-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:sumo)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{64})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.telegram-bot-api-token.telegram-bot-api-token + message: A gitleaks telegram-bot-api-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i:(?:telegr)(?:[0-9a-z\(-_\t .\\]{0,40})(?:[\s|']|[\s|"]){0,3})(?:=|\|\|:|<=|=>|:|\?=|\()(?:'|\"|\s|=|\x60){0,5}([0-9]{5,16}:A[a-z0-9_\-]{34})(?:['|\"|\n|\r|\s|\x60|;|\\]|$) +- id: generic.secrets.gitleaks.travisci-access-token.travisci-access-token + message: A gitleaks travisci-access-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:travis)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{22})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.twilio-api-key.twilio-api-key + message: A gitleaks twilio-api-key was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: SK[0-9a-fA-F]{32} +- id: generic.secrets.gitleaks.twitch-api-token.twitch-api-token + message: A gitleaks twitch-api-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:twitch)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{30})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.twitter-access-secret.twitter-access-secret + message: A gitleaks twitter-access-secret was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:twitter)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{45})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.twitter-access-token.twitter-access-token + message: A gitleaks twitter-access-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:twitter)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([0-9]{15,25}-[a-zA-Z0-9]{20,40})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.twitter-api-key.twitter-api-key + message: A gitleaks twitter-api-key was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:twitter)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{25})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.twitter-api-secret.twitter-api-secret + message: A gitleaks twitter-api-secret was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:twitter)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{50})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.twitter-bearer-token.twitter-bearer-token + message: A gitleaks twitter-bearer-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:twitter)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}(A{22}[a-zA-Z0-9%]{80,100})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.typeform-api-token.typeform-api-token + message: A gitleaks typeform-api-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:typeform)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}(tfp_[a-z0-9\-_\.=]{59})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.vault-batch-token.vault-batch-token + message: A gitleaks vault-batch-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)\b(hvb\.[a-z0-9_-]{138,212})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.vault-service-token.vault-service-token + message: A gitleaks vault-service-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)\b(hvs\.[a-z0-9_-]{90,100})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.yandex-access-token.yandex-access-token + message: A gitleaks yandex-access-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:yandex)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}(t1\.[A-Z0-9a-z_-]+[=]{0,2}\.[A-Z0-9a-z_-]{86}[=]{0,2})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.yandex-api-key.yandex-api-key + message: A gitleaks yandex-api-key was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:yandex)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}(AQVN[A-Za-z0-9_\-]{35,38})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.yandex-aws-access-token.yandex-aws-access-token + message: A gitleaks yandex-aws-access-token was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:yandex)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}(YC[a-zA-Z0-9_\-]{38})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.gitleaks.zendesk-secret-key.zendesk-secret-key + message: A gitleaks zendesk-secret-key was detected which attempts to identify hard-coded credentials. It is not recommended to store credentials in source-code, as this risks secrets being leaked and used by either an internal or external malicious adversary. It is recommended to use environment variables to securely provide credentials or retrieve credentials from a secure vault or HSM (Hardware Security Module). + languages: + - regex + severity: INFO + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-798: Use of Hard-coded Credentials" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/zricethezav/gitleaks/tree/master/cmd/generate/config/rules + subcategory: + - vuln + technology: + - gitleaks + patterns: + - pattern-regex: (?i)(?:zendesk)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{40})(?:['|\"|\n|\r|\s|\x60|;]|$) +- id: generic.secrets.security.detected-amazon-mws-auth-token.detected-amazon-mws-auth-token + pattern-regex: amzn\.mws\.[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} + languages: [regex] + message: Amazon MWS Auth Token detected + severity: ERROR + metadata: + cwe: + - 'CWE-798: Use of Hard-coded Credentials' + source-rule-url: https://github.com/dxa4481/truffleHogRegexes/blob/master/truffleHogRegexes/regexes.json + category: security + technology: + - secrets + - aws + confidence: LOW + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH +- id: generic.secrets.security.detected-artifactory-password.detected-artifactory-password + patterns: + - pattern-regex: (?\bAP[\dABCDEF][a-zA-Z0-9]{8,}) + - pattern-regex: .*(?i)arti[-_]?factory.* + - pattern-not-regex: .*(?i)sha(1|2|3|118|256|512).* + - pattern-not-regex: (?i)-----\s*?BEGIN[ A-Z0-9_-]*? KEY( BLOCK)?-----[\s\S]*?-----\s*?END[ A-Z0-9_-]*?\s*?----- + - metavariable-analysis: + analyzer: entropy + metavariable: $ITEM + - pattern-not-regex: (\w|\.|\*)\1{4} + languages: + - regex + paths: + exclude: + - "*.svg" + - "*go.sum" + - "*package.json" + - "*cargo.lock" + - "*package-lock.json" + - "*bundle.js" + - "*pnpm-lock*" + - "*Podfile.lock" + - "*/openssl/*.h" + - "*.xcscmblueprint" + message: Artifactory token detected + severity: ERROR + metadata: + cwe: + - "CWE-798: Use of Hard-coded Credentials" + source-rule-url: https://github.com/Yelp/detect-secrets/blob/master/detect_secrets/plugins/artifactory.py + category: security + technology: + - secrets + - artifactory + confidence: LOW + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH + license: Commons Clause License Condition v1.0[LGPL-2.1-only] +- id: generic.secrets.security.detected-artifactory-token.detected-artifactory-token + patterns: + - pattern-regex: | + \bAKC[a-zA-Z0-9]{10,} + - pattern-not-regex: | + sha(128|256|512).* + - pattern-not-regex: (?s)---BEGIN.*---\Z + languages: [regex] + paths: + exclude: + - "*.svg" + - "*go.sum" + - "*package.json" + - "*package-lock.json" + - "*bundle.js" + - "*pnpm-lock*" + - "*Podfile.lock" + - "*/openssl/*.h" + - "*.xcscmblueprint" + - "*cargo.lock" + message: Artifactory token detected + severity: ERROR + metadata: + cwe: + - 'CWE-798: Use of Hard-coded Credentials' + source-rule-url: https://github.com/Yelp/detect-secrets/blob/master/detect_secrets/plugins/artifactory.py + category: security + technology: + - secrets + - artifactory + confidence: LOW + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH + +- id: generic.secrets.security.detected-aws-access-key-id-value.detected-aws-access-key-id-value + patterns: + - pattern-regex: \b(A3T[A-Z0-9]|AKIA|AGPA|AROA|AIPA|ANPA|ANVA|ASIA)[A-Z0-9]{16}\b + - pattern-not-regex: (?i)example|sample|test|fake + languages: [regex] + message: AWS Access Key ID Value detected. This is a sensitive credential and should not be hardcoded + here. Instead, read this value from an environment variable or keep it in a separate, private file. + severity: ERROR + metadata: + cwe: + - 'CWE-798: Use of Hard-coded Credentials' + source-rule-url: https://github.com/grab/secret-scanner/blob/master/scanner/signatures/pattern.go + category: security + technology: + - secrets + - aws + confidence: LOW + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH +- id: generic.secrets.security.detected-aws-account-id.detected-aws-account-id + patterns: + - pattern-either: + - pattern: | + $ACCOUNT_ID = $SECRET + - pattern: | + $ACCOUNT_ID : $SECRET + - pattern: | + $ACCOUNT_ID => $SECRET + - pattern: | + $ACCOUNT_ID = "$SECRET" + - pattern: | + $ACCOUNT_ID : "$SECRET" + - pattern: | + $ACCOUNT_ID => "$SECRET" + - pattern: | + "$ACCOUNT_ID" = "$SECRET" + - pattern: | + "$ACCOUNT_ID" : "$SECRET" + - pattern: | + "$ACCOUNT_ID" => "$SECRET" + - metavariable-analysis: + metavariable: $SECRET + analyzer: entropy + - metavariable-regex: + metavariable: $SECRET + regex: ^((?!(12345|0000).*)[0-9]{12})$ + - metavariable-regex: + metavariable: $ACCOUNT_ID + regex: (AWS|aws|Aws)?_?(ACCOUNT|account|Account)_?(ID|id|Id)?("|')? + languages: + - generic + message: AWS Account ID detected. While not considered sensitive information, it is important + to use them and share them carefully. For that reason it would be preferrable avoiding to + hardcoded it here. Instead, read the value from an environment variable or + keep the value in a separate, private file. + severity: ERROR + metadata: + cwe: + - "CWE-798: Use of Hard-coded Credentials" + source-rule-url: https://github.com/grab/secret-scanner/blob/master/scanner/signatures/pattern.go + category: security + technology: + - secrets + - aws + confidence: LOW + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH + license: Commons Clause License Condition v1.0[LGPL-2.1-only] +- id: generic.secrets.security.detected-aws-appsync-graphql-key.detected-aws-appsync-graphql-key + pattern-regex: da2-[a-z0-9]{26} + languages: [regex] + message: AWS AppSync GraphQL Key detected + severity: ERROR + metadata: + cwe: + - 'CWE-798: Use of Hard-coded Credentials' + source-rule-url: https://github.com/dxa4481/truffleHogRegexes/blob/master/truffleHogRegexes/regexes.json + category: security + technology: + - secrets + - appsync + confidence: LOW + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH + +- id: generic.secrets.security.detected-aws-secret-access-key.detected-aws-secret-access-key + patterns: + - pattern-regex: |- + (("|'|`)?((?i)aws)_?\w*((?i)secret)_?\w*("|'|`)?\s{0,50}(:|=>|=)\s{0,50}("|'|`)?[A-Za-z0-9/+=]{40}("|'|`)?) + - pattern-not-regex: (?i)example|sample|test|fake|xxxxxx + languages: [regex] + message: AWS Secret Access Key detected + severity: ERROR + metadata: + cwe: + - 'CWE-798: Use of Hard-coded Credentials' + source-rule-url: https://github.com/grab/secret-scanner/blob/master/scanner/signatures/pattern.go + category: security + technology: + - secrets + - aws + confidence: LOW + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH + +- id: generic.secrets.security.detected-aws-session-token.detected-aws-session-token + patterns: + - pattern-regex: ((?i)AWS_SESSION_TOKEN)\s*(:|=>|=)\s*(?P[A-Za-z0-9/+=]{16,}) + - pattern-not-regex: (?i)example|sample|test|fake + - metavariable-analysis: + analyzer: entropy + metavariable: $TOKEN + languages: [regex] + message: AWS Session Token detected + severity: ERROR + metadata: + cwe: + - 'CWE-798: Use of Hard-coded Credentials' + source-rule-url: https://github.com/grab/secret-scanner/blob/master/scanner/signatures/pattern.go + category: security + technology: + - secrets + - aws + confidence: LOW + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH +- id: generic.secrets.security.detected-bcrypt-hash.detected-bcrypt-hash + pattern-regex: \$2[aby]?\$[\d]+\$[./A-Za-z0-9]{53} + languages: [regex] + message: bcrypt hash detected + severity: ERROR + metadata: + cwe: + - 'CWE-798: Use of Hard-coded Credentials' + category: security + technology: + - secrets + - bcrypt + confidence: LOW + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH +- id: generic.secrets.security.detected-codeclimate.detected-codeclimate + pattern-regex: |- + (?i)codeclima.{0,50}["|'|`]?[0-9a-f]{64}["|'|`]? + languages: [regex] + message: CodeClimate detected + severity: ERROR + metadata: + cwe: + - 'CWE-798: Use of Hard-coded Credentials' + source-rule-url: https://github.com/grab/secret-scanner/blob/master/scanner/signatures/pattern.go + category: security + technology: + - secrets + - codeclimate + confidence: LOW + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH +- id: generic.secrets.security.detected-etc-shadow.detected-etc-shadow + patterns: + - pattern-regex: ^(\s*)(?Proot:[x!*]*:[0-9]*:[0-9]*) + - focus-metavariable: $ROOT + languages: [regex] + message: linux shadow file detected + severity: ERROR + metadata: + cwe: + - 'CWE-798: Use of Hard-coded Credentials' + category: security + technology: + - secrets + confidence: LOW + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + +- id: generic.secrets.security.detected-facebook-access-token.detected-facebook-access-token + pattern-either: + - pattern-regex: EAACEdEose0cBA[0-9A-Za-z]+ + - pattern-regex: EAAAACZAVC6ygB[0-9A-Za-z]+ + - pattern-regex: EAAAAZAw4[0-9A-Za-z]+ + languages: [regex] + message: Facebook Access Token detected + severity: ERROR + metadata: + cwe: + - 'CWE-798: Use of Hard-coded Credentials' + source-rule-url: https://github.com/grab/secret-scanner/blob/master/scanner/signatures/pattern.go + category: security + technology: + - secrets + - facebook + confidence: LOW + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM +- id: generic.secrets.security.detected-facebook-oauth.detected-facebook-oauth + pattern-regex: |- + [fF][aA][cC][eE][bB][oO][oO][kK].*[tT][oO][kK][eE][nN].*['|"]?[0-9a-f]{32}['|"]? + languages: [regex] + message: Facebook OAuth detected + severity: ERROR + metadata: + cwe: + - 'CWE-798: Use of Hard-coded Credentials' + source-rule-url: https://github.com/dxa4481/truffleHogRegexes/blob/master/truffleHogRegexes/regexes.json + category: security + technology: + - secrets + - facebook + confidence: LOW + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM +- id: generic.secrets.security.detected-generic-api-key.detected-generic-api-key + patterns: + - pattern-regex: "[aA][pP][iI]_?[kK][eE][yY][=_:\\s-]+['|\"]?(?[0-9a-zA-Z]{32,45})['|\"]?" + - metavariable-analysis: + analyzer: entropy + metavariable: $SECRET + languages: [regex] + message: Generic API Key detected + severity: ERROR + metadata: + source-rule-url: https://github.com/dxa4481/truffleHogRegexes/blob/master/truffleHogRegexes/regexes.json + category: security + technology: + - secrets + confidence: LOW + references: + - https://github.com/dxa4481/truffleHogRegexes/blob/master/truffleHogRegexes/regexes.json + owasp: + - A07:2021 - Identification and Authentication Failures + cwe: + - 'CWE-798: Use of Hard-coded Credentials' + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM +- id: generic.secrets.security.detected-generic-secret.detected-generic-secret + patterns: + - pattern-regex: |- + [sS][eE][cC][rR][eE][tT][:= \t]*['|\"]?(?[0-9a-zA-Z]{32,45})['|\"]? + - metavariable-analysis: + analyzer: entropy + metavariable: $SECRET + languages: [regex] + message: Generic Secret detected + severity: ERROR + metadata: + cwe: + - 'CWE-798: Use of Hard-coded Credentials' + source-rule-url: https://github.com/dxa4481/truffleHogRegexes/blob/master/truffleHogRegexes/regexes.json + category: security + technology: + - secrets + confidence: LOW + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM +- id: generic.secrets.security.detected-github-token.detected-github-token + patterns: + - pattern-either: + - pattern: | + $VAR = $SECRET + - pattern: | + $VAR: $SECRET + - pattern: | + $VAR = '$SECRET' + - pattern: | + $VAR: '$SECRET' + - pattern: | + '$VAR' = '$SECRET' + - pattern: | + '$VAR': '$SECRET' + - pattern: | + "[hH][tT][tT][pP][sS]?://.*$SECRET.*" + - metavariable-regex: + metavariable: $SECRET + regex: gh[pousr]_[A-Za-z0-9_]{36,251} + - metavariable-analysis: + analyzer: entropy + metavariable: $SECRET + languages: [generic] + message: GitHub Token detected + severity: ERROR + metadata: + cwe: + - 'CWE-798: Use of Hard-coded Credentials' + source-rule-url: https://github.blog/changelog/2021-03-04-authentication-token-format-updates/ + category: security + technology: + - secrets + - github + confidence: LOW + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM +- id: generic.secrets.security.detected-google-api-key.detected-google-api-key + patterns: + - pattern-regex: \bAIzaSy[0-9A-Za-z-_]{33}\b + - pattern-not-regex: \bAIzaSy[0-9A-Za-z-_]{33}\b[=] + languages: + - regex + message: Google API Key Detected + severity: ERROR + metadata: + cwe: + - 'CWE-798: Use of Hard-coded Credentials' + source-rule-url: https://github.com/dxa4481/truffleHogRegexes/blob/master/truffleHogRegexes/regexes.json + category: security + technology: + - secrets + - google + license: Commons Clause License Condition v1.0[LGPL-2.1-only] + confidence: LOW + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM +- id: generic.secrets.security.detected-google-cloud-api-key.detected-google-cloud-api-key + pattern-regex: |- + AIza[0-9A-Za-z\\-_]{35} + languages: [regex] + message: Google Cloud API Key detected + severity: ERROR + metadata: + cwe: + - 'CWE-798: Use of Hard-coded Credentials' + source-rule-url: https://github.com/grab/secret-scanner/blob/master/scanner/signatures/pattern.go + category: security + technology: + - secrets + - google-cloud + confidence: LOW + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM +- id: generic.secrets.security.detected-google-gcm-service-account.detected-google-gcm-service-account + pattern-regex: |- + (("|'|`)?type("|'|`)?\s{0,50}(:|=>|=)\s{0,50}("|'|`)?service_account("|'|`)?,?) + languages: [regex] + message: Google (GCM) Service account detected + severity: ERROR + metadata: + cwe: + - 'CWE-798: Use of Hard-coded Credentials' + source-rule-url: https://github.com/grab/secret-scanner/blob/master/scanner/signatures/pattern.go + category: security + technology: + - secrets + - google-cloud + confidence: LOW + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM +- id: generic.secrets.security.detected-google-oauth-access-token.detected-google-oauth-access-token + pattern-regex: ya29\.[0-9A-Za-z\-_]+ + languages: [regex] + message: Google OAuth Access Token detected + severity: ERROR + metadata: + cwe: + - 'CWE-798: Use of Hard-coded Credentials' + source-rule-url: https://github.com/dxa4481/truffleHogRegexes/blob/master/truffleHogRegexes/regexes.json + category: security + technology: + - secrets + - google + confidence: LOW + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM +- id: generic.secrets.security.detected-google-oauth.detected-google-oauth-url + pattern-regex: '[0-9]+-[0-9A-Za-z_]{32}\.apps\.googleusercontent\.com' + languages: [regex] + message: Google OAuth url detected + severity: ERROR + metadata: + cwe: + - 'CWE-798: Use of Hard-coded Credentials' + source-rule-url: https://github.com/dxa4481/truffleHogRegexes/blob/master/truffleHogRegexes/regexes.json + category: security + technology: + - secrets + - google + confidence: LOW + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM +- id: generic.secrets.security.detected-heroku-api-key.detected-heroku-api-key + pattern-regex: |- + [hH][eE][rR][oO][kK][uU].*[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12} + languages: [regex] + message: Heroku API Key detected + severity: ERROR + metadata: + cwe: + - 'CWE-798: Use of Hard-coded Credentials' + source-rule-url: https://github.com/dxa4481/truffleHogRegexes/blob/master/truffleHogRegexes/regexes.json + category: security + technology: + - secrets + - heroku + confidence: LOW + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM +- id: generic.secrets.security.detected-hockeyapp.detected-hockeyapp + pattern-regex: |- + (?i)hockey.{0,50}(\\\"|'|`)?[0-9a-f]{32}(\\\"|'|`)? + languages: [regex] + message: HockeyApp detected + severity: ERROR + metadata: + cwe: + - 'CWE-798: Use of Hard-coded Credentials' + source-rule-url: https://github.com/grab/secret-scanner/blob/master/scanner/signatures/pattern.go + category: security + technology: + - secrets + - hockeyapp + confidence: LOW + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM +- id: generic.secrets.security.detected-jwt-token.detected-jwt-token + pattern-regex: |- + eyJ[A-Za-z0-9-_=]{14,}\.[A-Za-z0-9-_=]{13,}\.?[A-Za-z0-9-_.+/=]*? + languages: [regex] + message: JWT token detected + severity: ERROR + metadata: + source-rule-url: https://github.com/Yelp/detect-secrets/blob/master/detect_secrets/plugins/jwt.py + category: security + technology: + - secrets + - jwt + confidence: LOW + references: + - https://semgrep.dev/blog/2020/hardcoded-secrets-unverified-tokens-and-other-common-jwt-mistakes/ + cwe: + - 'CWE-321: Use of Hard-coded Cryptographic Key' + owasp: + - A02:2021 - Cryptographic Failures + subcategory: + - audit + likelihood: LOW + impact: MEDIUM +- id: generic.secrets.security.detected-kolide-api-key.detected-kolide-api-key + pattern-regex: k2sk_v[0-9]_[0-9a-zA-Z]{24} + languages: [regex] + message: Kolide API Key detected + severity: ERROR + metadata: + cwe: + - 'CWE-798: Use of Hard-coded Credentials' + category: security + technology: + - secrets + - kolide + confidence: LOW + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM +- id: generic.secrets.security.detected-mailchimp-api-key.detected-mailchimp-api-key + pattern-regex: '[0-9a-f]{32}-us[0-9]{1,2}' + languages: [regex] + message: MailChimp API Key detected + severity: ERROR + metadata: + source-rule-url: https://github.com/dxa4481/truffleHogRegexes/blob/master/truffleHogRegexes/regexes.json + category: security + cwe: + - 'CWE-798: Use of Hard-coded Credentials' + technology: + - secrets + - mailchimp + confidence: LOW + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM +- id: generic.secrets.security.detected-mailgun-api-key.detected-mailgun-api-key + pattern-regex: key-[0-9a-zA-Z]{32} + languages: [regex] + message: Mailgun API Key detected + severity: ERROR + metadata: + cwe: + - 'CWE-798: Use of Hard-coded Credentials' + source-rule-url: https://github.com/dxa4481/truffleHogRegexes/blob/master/truffleHogRegexes/regexes.json + category: security + technology: + - secrets + - mailgun + confidence: LOW + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM +- id: generic.secrets.security.detected-npm-registry-auth-token.detected-npm-registry-auth-token + patterns: + - pattern: $AUTHTOKEN = $VALUE + - metavariable-regex: + metavariable: $AUTHTOKEN + regex: _(authToken|auth|password) + - pattern-not: $AUTHTOKEN = ${...} + languages: [generic] + message: NPM registry authentication token detected + paths: + include: + - '*npmrc*' + severity: ERROR + metadata: + cwe: + - 'CWE-798: Use of Hard-coded Credentials' + category: security + technology: + - secrets + - npm + confidence: LOW + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM +- id: generic.secrets.security.detected-outlook-team.detected-outlook-team + pattern-regex: |- + https://outlook\.office\.com/webhook/[0-9a-f-]{36} + languages: [regex] + message: Outlook Team detected + severity: ERROR + metadata: + cwe: + - 'CWE-798: Use of Hard-coded Credentials' + source-rule-url: https://github.com/grab/secret-scanner/blob/master/scanner/signatures/pattern.go + category: security + technology: + - secrets + - outlook + confidence: LOW + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM +- id: generic.secrets.security.detected-paypal-braintree-access-token.detected-paypal-braintree-access-token + pattern-regex: access_token\$production\$[0-9a-z]{16}\$[0-9a-z]{32} + languages: [regex] + message: PayPal Braintree Access Token detected + severity: ERROR + metadata: + cwe: + - 'CWE-798: Use of Hard-coded Credentials' + source-rule-url: https://github.com/dxa4481/truffleHogRegexes/blob/master/truffleHogRegexes/regexes.json + category: security + technology: + - secrets + - paypal + - braintree + confidence: LOW + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM +- id: generic.secrets.security.detected-pgp-private-key-block.detected-pgp-private-key-block + pattern-regex: '-----BEGIN PGP PRIVATE KEY BLOCK-----' + languages: [regex] + message: >- + Something that looks like a PGP private key block is detected. This is a potential + hardcoded secret that could be leaked if this code is committed. + Instead, remove this code block from the commit. + severity: ERROR + metadata: + cwe: + - 'CWE-798: Use of Hard-coded Credentials' + source-rule-url: https://github.com/dxa4481/truffleHogRegexes/blob/master/truffleHogRegexes/regexes.json + category: security + technology: + - secrets + confidence: LOW + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM +- id: generic.secrets.security.detected-picatic-api-key.detected-picatic-api-key + pattern-regex: sk_live_[0-9a-z]{32} + languages: [regex] + message: Picatic API Key detected + severity: ERROR + metadata: + cwe: + - 'CWE-798: Use of Hard-coded Credentials' + source-rule-url: https://github.com/dxa4481/truffleHogRegexes/blob/master/truffleHogRegexes/regexes.json + category: security + technology: + - secrets + - picatic + confidence: LOW + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM +- id: generic.secrets.security.detected-private-key.detected-private-key + patterns: + - pattern-either: + - patterns: + - pattern: '-----BEGIN $TYPE PRIVATE KEY----- $KEY' + - metavariable-regex: + metavariable: $TYPE + regex: (?i)([dr]sa|ec|openssh|encrypted)? + - patterns: + - pattern: | + -----BEGIN PRIVATE KEY----- + $KEY + - metavariable-analysis: + metavariable: $KEY + analyzer: entropy + languages: [generic] + message: Private Key detected. This is a sensitive credential and should not be hardcoded here. Instead, + store this in a separate, private file. + severity: ERROR + metadata: + cwe: + - 'CWE-798: Use of Hard-coded Credentials' + source-rule-url: https://github.com/grab/secret-scanner/blob/master/scanner/signatures/pattern.go + category: security + technology: + - secrets + confidence: LOW + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM +- id: generic.secrets.security.detected-sauce-token.detected-sauce-token + pattern-regex: |- + (?i)sauce.{0,50}(\\\"|'|`)?[0-9a-f-]{36}(\\\"|'|`)? + languages: [regex] + message: Sauce Token detected + severity: ERROR + metadata: + cwe: + - 'CWE-798: Use of Hard-coded Credentials' + source-rule-url: https://github.com/grab/secret-scanner/blob/master/scanner/signatures/pattern.go + category: security + technology: + - secrets + - sauce + confidence: LOW + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM +- id: generic.secrets.security.detected-sendgrid-api-key.detected-sendgrid-api-key + pattern-regex: |- + SG\.[a-zA-Z0-9]{22}\.[a-zA-Z0-9-]{43}\b + languages: [regex] + message: SendGrid API Key detected + severity: ERROR + metadata: + cwe: + - 'CWE-798: Use of Hard-coded Credentials' + source-rule-url: https://github.com/narendrakadali/gitrob/blob/master/rules/contentsignatures.json + category: security + technology: + - secrets + - sendgrid + confidence: LOW + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM +- id: generic.secrets.security.detected-slack-token.detected-slack-token + pattern-either: + - pattern-regex: (xox[pboa]-[0-9]{12}-[0-9]{12}-[0-9]{12}-[a-z0-9]{32}) + - pattern-regex: xox.-[0-9]{12}-[0-9]{12}-[0-9a-zA-Z]{24} + languages: [regex] + message: Slack Token detected + severity: ERROR + metadata: + cwe: + - 'CWE-798: Use of Hard-coded Credentials' + source-rule-url: https://github.com/dxa4481/truffleHogRegexes/blob/master/truffleHogRegexes/regexes.json + references: + - https://github.com/davidburkitt/python-secret-scanner/blob/335a1f6dab8de59cf39063e57aea39a58951e939/patterns.txt#L58 + category: security + technology: + - secrets + - slack + confidence: LOW + owasp: + - A07:2021 - Identification and Authentication Failures + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM +- id: generic.secrets.security.detected-slack-webhook.detected-slack-webhook + pattern-regex: https://hooks\.slack\.com/services/T[a-zA-Z0-9_]{8,10}/B[a-zA-Z0-9_]{8,10}/[a-zA-Z0-9_]{24} + languages: [regex] + message: Slack Webhook detected + severity: ERROR + metadata: + references: + - https://api.slack.com/messaging/webhooks + source-rule-url: https://github.com/dxa4481/truffleHogRegexes/blob/master/truffleHogRegexes/regexes.json + category: security + technology: + - secrets + - slack + confidence: LOW + owasp: + - A07:2021 - Identification and Authentication Failures + cwe: + - 'CWE-798: Use of Hard-coded Credentials' + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM +- id: generic.secrets.security.detected-snyk-api-key.detected-snyk-api-key + pattern-regex: |- + (?i)snyk.{0,50}['|"|`]?[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}['"\s]? + languages: [regex] + message: Snyk API Key detected + severity: ERROR + metadata: + cwe: + - 'CWE-798: Use of Hard-coded Credentials' + category: security + technology: + - secrets + - snyk + confidence: LOW + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM +- id: generic.secrets.security.detected-softlayer-api-key.detected-softlayer-api-key + pattern-regex: |- + (?i)softlayer.{0,50}["|'|`]?[a-z0-9]{64}["|'|`]? + languages: [regex] + message: SoftLayer API Key detected + severity: ERROR + metadata: + cwe: + - 'CWE-798: Use of Hard-coded Credentials' + source-rule-url: https://github.com/Yelp/detect-secrets/blob/master/detect_secrets/plugins/softlayer.py + category: security + technology: + - secrets + - softlayer + confidence: LOW + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM +- id: generic.secrets.security.detected-sonarqube-docs-api-key.detected-sonarqube-docs-api-key + pattern-regex: |- + (?i)sonar.{0,50}(\\\"|'|`)?[0-9a-f]{40}(\\\"|'|`)? + languages: [regex] + message: SonarQube Docs API Key detected + severity: ERROR + paths: + exclude: + - "*.svg" + - "*go.sum" + - "*cargo.lock" + - "*package.json" + - "*yarn.lock" + - "*package-lock.json" + - "*bundle.js" + - "*pnpm-lock*" + - "*Podfile.lock" + - "*/openssl/*.h" + - "*.xcscmblueprint" + metadata: + cwe: + - 'CWE-798: Use of Hard-coded Credentials' + source-rule-url: https://github.com/grab/secret-scanner/blob/master/scanner/signatures/pattern.go + category: security + technology: + - secrets + - sonarqube + confidence: LOW + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM +- id: generic.secrets.security.detected-square-access-token.detected-square-access-token + pattern-regex: sq0atp-[0-9A-Za-z\-_]{22} + languages: [regex] + message: Square Access Token detected + severity: ERROR + metadata: + cwe: + - 'CWE-798: Use of Hard-coded Credentials' + source-rule-url: https://github.com/dxa4481/truffleHogRegexes/blob/master/truffleHogRegexes/regexes.json + category: security + technology: + - secrets + - square + confidence: LOW + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM +- id: generic.secrets.security.detected-square-oauth-secret.detected-square-oauth-secret + pattern-regex: |- + sq0csp-[0-9A-Za-z\\\-_]{43} + languages: [regex] + message: Square OAuth Secret detected + severity: ERROR + metadata: + cwe: + - 'CWE-798: Use of Hard-coded Credentials' + source-rule-url: https://github.com/dxa4481/truffleHogRegexes/blob/master/truffleHogRegexes/regexes.json + references: + - https://github.com/Yelp/detect-secrets/blob/master/tests/plugins/square_oauth_test.py + category: security + technology: + - secrets + - square + confidence: LOW + owasp: + - A07:2021 - Identification and Authentication Failures + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM +- id: generic.secrets.security.detected-ssh-password.detected-ssh-password + pattern-regex: |- + sshpass -p\s*['|\\\"][^%] + languages: [regex] + message: SSH Password detected + severity: ERROR + metadata: + cwe: + - 'CWE-798: Use of Hard-coded Credentials' + source-rule-url: https://github.com/grab/secret-scanner/blob/master/scanner/signatures/pattern.go + category: security + technology: + - secrets + - ssh + confidence: LOW + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM +- id: generic.secrets.security.detected-stripe-api-key.detected-stripe-api-key + pattern-regex: sk_live_[0-9a-zA-Z]{24} + languages: [regex] + message: Stripe API Key detected + severity: ERROR + metadata: + cwe: + - 'CWE-798: Use of Hard-coded Credentials' + source-rule-url: https://github.com/dxa4481/truffleHogRegexes/blob/master/truffleHogRegexes/regexes.json + category: security + technology: + - secrets + - stripe + confidence: LOW + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM +- id: generic.secrets.security.detected-stripe-restricted-api-key.detected-stripe-restricted-api-key + pattern-regex: rk_live_[0-9a-zA-Z]{24} + languages: [regex] + message: Stripe Restricted API Key detected + severity: ERROR + metadata: + cwe: + - 'CWE-798: Use of Hard-coded Credentials' + source-rule-url: https://github.com/dxa4481/truffleHogRegexes/blob/master/truffleHogRegexes/regexes.json + category: security + technology: + - secrets + - stripe + confidence: MEDIUM + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: LOW +- id: generic.secrets.security.detected-telegram-bot-api-key.detected-telegram-bot-api-key + patterns: + - pattern-regex: '[0-9]+:AA[0-9A-Za-z\-_]{33}' + - pattern-not-regex: go\.mod.* + - pattern-not-regex: v[\d]+\.[\d]+\.[\d]+.* + languages: + - regex + message: Telegram Bot API Key detected + severity: ERROR + metadata: + cwe: + - 'CWE-798: Use of Hard-coded Credentials' + source-rule-url: https://github.com/dxa4481/truffleHogRegexes/blob/master/truffleHogRegexes/regexes.json + category: security + technology: + - secrets + - telegram + license: Commons Clause License Condition v1.0[LGPL-2.1-only] + confidence: LOW + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM +- id: generic.secrets.security.detected-twilio-api-key.detected-twilio-api-key + pattern-regex: SK[0-9a-fA-F]{32} + languages: [regex] + message: Twilio API Key detected + severity: ERROR + metadata: + cwe: + - 'CWE-798: Use of Hard-coded Credentials' + source-rule-url: https://github.com/dxa4481/truffleHogRegexes/blob/master/truffleHogRegexes/regexes.json + category: security + technology: + - secrets + - twilio + confidence: LOW + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM +- id: generic.secrets.security.detected-username-and-password-in-uri.detected-username-and-password-in-uri + patterns: + - pattern: $PROTOCOL://$...USERNAME:$...PASSWORD@$END + - metavariable-regex: + metavariable: $...USERNAME + regex: \A({?)([A-Za-z])([A-Za-z0-9_-]){5,31}(}?)\Z + - metavariable-regex: + metavariable: $...PASSWORD + regex: (?!.*[\s])(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~]){6,32} + - metavariable-regex: + metavariable: $PROTOCOL + regex: (.*http.*)|(.*sql.*)|(.*ftp.*)|(.*smtp.*) + languages: + - generic + message: Username and password in URI detected + severity: ERROR + metadata: + owasp: + - A07:2021 - Identification and Authentication Failures + cwe: + - 'CWE-798: Use of Hard-coded Credentials' + references: + - https://github.com/grab/secret-scanner/blob/master/scanner/signatures/pattern.go + category: security + technology: + - secrets + confidence: MEDIUM + license: Commons Clause License Condition v1.0[LGPL-2.1-only] + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM +- id: generic.secrets.security.google-maps-apikeyleak.google-maps-apikeyleak + patterns: + - pattern-regex: ^(AIza[0-9A-Za-z_-]{35}(?!\S))$ + message: Detects potential Google Maps API keys in code + languages: + - generic + severity: WARNING + metadata: + description: Detects potential Google Maps API keys in code + severity: MEDIUM + category: security + confidence: MEDIUM + impact: HIGH + likelihood: MEDIUM + subcategory: + - audit + owasp: + - A3:2017 Sensitive Data Exposure + references: + - https://ozguralp.medium.com/unauthorized-google-maps-api-key-usage-cases-and-why-you-need-to-care-1ccb28bf21e + cwe: + - "CWE-538: Insertion of Sensitive Information into Externally-Accessible File or Directory" + technology: + - Google Maps +- id: generic.unicode.security.bidi.contains-bidirectional-characters + patterns: + - pattern-either: + - pattern-regex: ‪ # left-to-right embedding (LRE) + - pattern-regex: ‫ # right-to-left embedding (RLE) + - pattern-regex: ‭ # left-to-right override (LRO) + - pattern-regex: ‮ # right-to-left override (RLO) + - pattern-regex: ⁦ # left-to-right isolate (LRI) + - pattern-regex: ⁧ # right-to-left isolate (RLI) + - pattern-regex: ⁨ # first strong isolate (FSI) + - pattern-regex: ‬ # pop directional formatting (PDF) + - pattern-regex: ⁩ # pop directional isolate (PDI) + message: >- + This code contains bidirectional (bidi) characters. While this is useful for support + of right-to-left languages such as Arabic or Hebrew, it can also be used to trick + language parsers into executing code in a manner that is different from how it + is + displayed in code editing and review tools. + If this is not what you were expecting, please review this code in an editor that + can reveal hidden Unicode characters. + metadata: + cwe: + - "CWE-94: Improper Control of Generation of Code ('Code Injection')" + category: security + technology: + - unicode + references: + - https://trojansource.codes/ + confidence: LOW + owasp: + - A03:2021 - Injection + cwe2022-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH + languages: + - bash + - c + - cpp + - csharp + - go + - java + - javascript + - json + - kotlin + - lua + - ocaml + - php + - python + - ruby + - rust + - scala + - sh + - typescript + - yaml + severity: WARNING +- id: generic.visualforce.security.ncino.html.usesriforcdns.use-sri-for-cdns + languages: + - generic + severity: WARNING + message: >- + Consuming CDNs without including a SubResource Integrity (SRI) can expose your + application and its users to compromised code. SRIs allow you to consume specific + versions of content where if even a single byte is compromised, the resource will + not be loaded. Add an integrity attribute to your + - pattern-not: + paths: + include: + - "*.component" + - "*.page" + +- id: generic.visualforce.security.ncino.xml.cspheaderattribute.csp-header-attribute + languages: + - generic + severity: INFO + message: >- + Visualforce Pages must have the cspHeader attribute set to true. + This attribute is available in API version 55 or higher. + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + references: + - https://help.salesforce.com/s/articleView?id=sf.csp_trusted_sites.htm&type=5 + category: security + subcategory: + - vuln + technology: + - salesforce + - visualforce + cwe2022-top25: true + cwe2021-top25: true + likelihood: HIGH + impact: MEDIUM + confidence: HIGH + patterns: + - pattern: ... + - pattern-not: ... + - pattern-not: ...... + - pattern-not: ...... + paths: + include: + - "*.page" +- id: generic.visualforce.security.ncino.xml.visualforceapiversion.visualforce-page-api-version + languages: + - generic + severity: WARNING + message: Visualforce Pages must use API version 55 or higher for required use of the cspHeader attribute set to true. + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + references: + - https://developer.salesforce.com/docs/atlas.en-us.api_meta.meta/api_meta/meta_pages.htm + category: security + subcategory: + - vuln + technology: + - salesforce + - visualforce + cwe2022-top25: true + cwe2021-top25: true + likelihood: HIGH + impact: MEDIUM + confidence: HIGH + patterns: + - pattern-inside: + - pattern-either: + - pattern-regex: '[>][0-9].[0-9][<]' + - pattern-regex: '[>][1-4][0-9].[0-9][<]' + - pattern-regex: '[>][5][0-4].[0-9][<]' + paths: + include: + - "*.page-meta.xml" + +- id: go.aws-lambda.security.database-sqli.database-sqli + languages: + - go + message: >- + Detected SQL statement that is tainted by `$EVENT` object. This could lead to SQL injection if the + variable is user-controlled + and not properly sanitized. In order to prevent SQL injection, + use parameterized queries or prepared statements instead. + You can use prepared statements with the 'Prepare' and 'PrepareContext' calls. + mode: taint + metadata: + references: + - https://pkg.go.dev/database/sql#DB.Query + category: security + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + cwe: + - "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')" + technology: + - aws-lambda + - database + - sql + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: HIGH + impact: MEDIUM + confidence: MEDIUM + pattern-sinks: + - patterns: + - focus-metavariable: $QUERY + - pattern-either: + - pattern: $DB.Exec($QUERY,...) + - pattern: $DB.ExecContent($QUERY,...) + - pattern: $DB.Query($QUERY,...) + - pattern: $DB.QueryContext($QUERY,...) + - pattern: $DB.QueryRow($QUERY,...) + - pattern: $DB.QueryRowContext($QUERY,...) + - pattern-inside: | + import "database/sql" + ... + pattern-sources: + - patterns: + - pattern-either: + - pattern-inside: | + func $HANDLER($CTX $CTXTYPE, $EVENT $TYPE, ...) {...} + ... + lambda.Start($HANDLER, ...) + - patterns: + - pattern-inside: | + func $HANDLER($EVENT $TYPE) {...} + ... + lambda.Start($HANDLER, ...) + - pattern-not-inside: | + func $HANDLER($EVENT context.Context) {...} + ... + lambda.Start($HANDLER, ...) + - focus-metavariable: $EVENT + severity: WARNING +- id: go.aws-lambda.security.tainted-sql-string.tainted-sql-string + languages: [go] + severity: ERROR + message: >- + Detected user input used to manually construct a SQL string. This is usually + bad practice because manual construction could accidentally result in a SQL + injection. An attacker could use a SQL injection to steal or modify contents + of the database. Instead, use a parameterized query which is available + by default in most database engines. Alternatively, consider using an + object-relational mapper (ORM) such as Sequelize which will protect your queries. + metadata: + references: + - https://owasp.org/www-community/attacks/SQL_Injection + category: security + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + cwe: + - "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')" + technology: + - aws-lambda + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: HIGH + impact: MEDIUM + confidence: MEDIUM + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - pattern-inside: | + func $HANDLER($CTX $CTXTYPE, $EVENT $TYPE, ...) {...} + ... + lambda.Start($HANDLER, ...) + - patterns: + - pattern-inside: | + func $HANDLER($EVENT $TYPE) {...} + ... + lambda.Start($HANDLER, ...) + - pattern-not-inside: | + func $HANDLER($EVENT context.Context) {...} + ... + lambda.Start($HANDLER, ...) + - focus-metavariable: $EVENT + pattern-sinks: + - patterns: + - pattern-either: + - patterns: + - pattern: | + "$SQLSTR" + ... + - metavariable-regex: + metavariable: $SQLSTR + regex: (?i)(\s*select|\s*delete|\s*insert|\s*create|\s*update|\s*alter|\s*drop).* + - patterns: + - pattern-either: + - pattern: fmt.Fprintf($F, "$SQLSTR", ...) + - pattern: fmt.Sprintf("$SQLSTR", ...) + - pattern: fmt.Printf("$SQLSTR", ...) + - metavariable-regex: + metavariable: $SQLSTR + regex: \s*(?i)(select|delete|insert|create|update|alter|drop)\b.*%(v|s|q).* + - pattern-not-inside: | + log.$PRINT(...) + pattern-sanitizers: + - pattern: strconv.Atoi(...) +- id: go.gorilla.security.audit.handler-assignment-from-multiple-sources.handler-assignment-from-multiple-sources + metadata: + cwe: + - 'CWE-289: Authentication Bypass by Alternate Name' + category: security + technology: + - gorilla + confidence: MEDIUM + license: Commons Clause License Condition v1.0[LGPL-2.1-only] + references: + - https://cwe.mitre.org/data/definitions/289.html + subcategory: + - audit + impact: MEDIUM + likelihood: LOW + mode: taint + pattern-sources: + - patterns: + - pattern-inside: | + func $HANDLER(..., $R *http.Request, ...) { + ... + } + - focus-metavariable: $R + - pattern-either: + - pattern: $R.query + pattern-sinks: + - patterns: + - pattern: | + $Y, err := store.Get(...) + ... + $VAR := $Y.Values[...] + ... + $VAR = $R + - focus-metavariable: $R + - patterns: + - pattern: | + $Y, err := store.Get(...) + ... + var $VAR $INT = $Y.Values["..."].($INT) + ... + $VAR = $R + - focus-metavariable: $R + message: >- + Variable $VAR is assigned from two different sources: '$Y' and '$R'. Make sure this is intended, + as this could cause logic bugs if they are treated as they are the same object. + languages: + - go + severity: WARNING +- id: go.gorilla.security.audit.session-cookie-missing-httponly.session-cookie-missing-httponly + patterns: + - pattern-not-inside: | + &sessions.Options{ + ..., + HttpOnly: true, + ..., + } + - pattern: | + &sessions.Options{ + ..., + } + message: >- + A session cookie was detected without setting the 'HttpOnly' flag. + The 'HttpOnly' flag for cookies instructs the browser to forbid + client-side scripts from reading the cookie which mitigates XSS + attacks. Set the 'HttpOnly' flag by setting 'HttpOnly' to 'true' + in the Options struct. + metadata: + cwe: + - "CWE-1004: Sensitive Cookie Without 'HttpOnly' Flag" + owasp: + - A05:2021 - Security Misconfiguration + references: + - https://github.com/0c34/govwa/blob/139693e56406b5684d2a6ae22c0af90717e149b8/user/session/session.go#L69 + category: security + technology: + - gorilla + confidence: MEDIUM + subcategory: + - audit + likelihood: LOW + impact: LOW + fix-regex: + regex: (HttpOnly\s*:\s+)false + replacement: \1true + severity: WARNING + languages: [go] +- id: go.gorilla.security.audit.session-cookie-missing-secure.session-cookie-missing-secure + patterns: + - pattern-not-inside: | + &sessions.Options{ + ..., + Secure: true, + ..., + } + - pattern: | + &sessions.Options{ + ..., + } + message: >- + A session cookie was detected without setting the 'Secure' flag. + The 'secure' flag for cookies prevents the client from transmitting + the cookie over insecure channels such as HTTP. Set the 'Secure' + flag by setting 'Secure' to 'true' in the Options struct. + metadata: + cwe: + - "CWE-614: Sensitive Cookie in HTTPS Session Without 'Secure' Attribute" + owasp: + - A05:2021 - Security Misconfiguration + references: + - https://github.com/0c34/govwa/blob/139693e56406b5684d2a6ae22c0af90717e149b8/user/session/session.go#L69 + category: security + technology: + - gorilla + confidence: MEDIUM + subcategory: + - audit + likelihood: LOW + impact: LOW + fix-regex: + regex: (Secure\s*:\s+)false + replacement: \1true + severity: WARNING + languages: [go] +- id: go.gorilla.security.audit.session-cookie-samesitenone.session-cookie-samesitenone + patterns: + - pattern-inside: | + &sessions.Options{ + ..., + SameSite: http.SameSiteNoneMode, + ..., + } + - pattern: | + &sessions.Options{ + ..., + } + message: Found SameSiteNoneMode setting in Gorilla session options. Consider setting + SameSite to Lax, Strict or Default for enhanced security. + metadata: + cwe: + - 'CWE-1275: Sensitive Cookie with Improper SameSite Attribute' + owasp: + - A05:2021 - Security Misconfiguration + references: + - https://pkg.go.dev/github.com/gorilla/sessions#Options + category: security + technology: + - gorilla + confidence: MEDIUM + subcategory: + - audit + likelihood: LOW + impact: LOW + fix-regex: + regex: (SameSite\s*:\s+)http.SameSiteNoneMode + replacement: \1http.SameSiteDefaultMode + severity: WARNING + languages: + - go +- id: go.gorilla.security.audit.websocket-missing-origin-check.websocket-missing-origin-check + patterns: + - pattern-inside: | + import ("github.com/gorilla/websocket") + ... + - patterns: + - pattern-not-inside: | + $UPGRADER = websocket.Upgrader{..., CheckOrigin: $FN ,...} + ... + - pattern-not-inside: | + $UPGRADER.CheckOrigin = $FN2 + ... + - pattern: | + $UPGRADER.Upgrade(...) + message: >- + The Origin header in the HTTP WebSocket handshake is used to guarantee that the + connection accepted by the WebSocket is from a trusted origin domain. Failure to enforce can + lead to Cross Site Request Forgery (CSRF). As per "gorilla/websocket" documentation: "A CheckOrigin function + should carefully validate the request origin to prevent cross-site request forgery." + languages: [go] + severity: WARNING + metadata: + category: security + cwe: + - 'CWE-352: Cross-Site Request Forgery (CSRF)' + owasp: + - A01:2021 - Broken Access Control + references: + - https://pkg.go.dev/github.com/gorilla/websocket#Upgrader + technology: + - gorilla + confidence: MEDIUM + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: LOW +- id: go.gorm.security.audit.gorm-dangerous-methods-usage.gorm-dangerous-method-usage + message: >- + Detected usage of dangerous method $METHOD which does not escape inputs (see link in references). + If the argument is user-controlled, this can lead to SQL injection. When using $METHOD function, + do not trust user-submitted data and only allow approved list of input (possibly, use an allowlist + approach). + severity: WARNING + languages: + - go + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - pattern: | + ($REQUEST : http.Request).$ANYTHING + - pattern: | + ($REQUEST : *http.Request).$ANYTHING + - metavariable-regex: + metavariable: $ANYTHING + regex: ^(BasicAuth|Body|Cookie|Cookies|Form|FormValue|GetBody|Host|MultipartReader|ParseForm|ParseMultipartForm|PostForm|PostFormValue|Referer|RequestURI|Trailer|TransferEncoding|UserAgent|URL)$ + pattern-sinks: + - patterns: + - pattern-inside: | + import ("gorm.io/gorm") + ... + - patterns: + - pattern-inside: | + func $VAL(..., $GORM *gorm.DB,... ) { + ... + } + - pattern-either: + - pattern: | + $GORM. ... .$METHOD($VALUE) + - pattern: | + $DB := $GORM. ... .$ANYTHING(...) + ... + $DB. ... .$METHOD($VALUE) + - focus-metavariable: $VALUE + - metavariable-regex: + metavariable: $METHOD + regex: ^(Order|Exec|Raw|Group|Having|Distinct|Select|Pluck)$ + pattern-sanitizers: + - pattern-either: + - pattern: strconv.Atoi(...) + - pattern: | + ($X: bool) + options: + interfile: true + metadata: + category: security + technology: + - gorm + cwe: + - "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')" + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + references: + - https://gorm.io/docs/security.html#SQL-injection-Methods + - https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html + confidence: HIGH + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: HIGH + impact: MEDIUM + interfile: true +- id: go.grpc.security.grpc-client-insecure-connection.grpc-client-insecure-connection + metadata: + cwe: + - 'CWE-300: Channel Accessible by Non-Endpoint' + references: + - https://blog.gopheracademy.com/advent-2019/go-grps-and-tls/#connection-without-encryption + category: security + technology: + - grpc + confidence: HIGH + owasp: + - A07:2021 - Identification and Authentication Failures + subcategory: + - audit + likelihood: LOW + impact: LOW + message: >- + Found an insecure gRPC connection using 'grpc.WithInsecure()'. This creates a + connection without encryption to a gRPC + server. A malicious attacker could tamper with the gRPC message, which could compromise + the machine. Instead, establish + a secure connection with an + SSL certificate using the 'grpc.WithTransportCredentials()' function. You can + create a create credentials using a 'tls.Config{}' + struct with 'credentials.NewTLS()'. The final fix looks like this: 'grpc.WithTransportCredentials(credentials.NewTLS())'. + languages: + - go + severity: ERROR + pattern: $GRPC.Dial($ADDR, ..., $GRPC.WithInsecure(...), ...) + fix-regex: + regex: (.*)WithInsecure\(.*?\) + replacement: \1WithTransportCredentials(credentials.NewTLS()) +- id: go.grpc.security.grpc-server-insecure-connection.grpc-server-insecure-connection + metadata: + cwe: + - 'CWE-300: Channel Accessible by Non-Endpoint' + references: + - https://blog.gopheracademy.com/advent-2019/go-grps-and-tls/#connection-without-encryption + category: security + technology: + - grpc + confidence: HIGH + owasp: + - A07:2021 - Identification and Authentication Failures + subcategory: + - audit + likelihood: LOW + impact: LOW + message: >- + Found an insecure gRPC server without 'grpc.Creds()' or options with credentials. + This allows for a connection without + encryption to this server. + A malicious attacker could tamper with the gRPC message, which could compromise + the machine. Include credentials derived + from an SSL certificate in order to create a secure gRPC connection. You can create + credentials using 'credentials.NewServerTLSFromFile("cert.pem", + "cert.key")'. + languages: + - go + severity: ERROR + mode: taint + pattern-sinks: + - requires: OPTIONS and not CREDS + pattern: grpc.NewServer($OPT, ...) + - requires: EMPTY_CONSTRUCTOR + pattern: grpc.NewServer() + pattern-sources: + - label: OPTIONS + pattern: grpc.ServerOption{ ... } + - label: CREDS + pattern: grpc.Creds(...) + - label: EMPTY_CONSTRUCTOR + pattern: grpc.NewServer() + +- id: go.jwt-go.security.audit.jwt-parse-unverified.jwt-go-parse-unverified + message: >- + Detected the decoding of a JWT token without a verify step. + Don't use `ParseUnverified` unless you know what you're doing + This method parses the token but doesn't validate the signature. It's only ever useful in cases where + you know the signature is valid (because it has been checked previously in the stack) and you want + to extract values from it. + metadata: + cwe: + - 'CWE-345: Insufficient Verification of Data Authenticity' + owasp: + - A08:2021 - Software and Data Integrity Failures + source-rule-url: https://semgrep.dev/blog/2020/hardcoded-secrets-unverified-tokens-and-other-common-jwt-mistakes/ + category: security + technology: + - jwt + confidence: MEDIUM + references: + - https://owasp.org/Top10/A08_2021-Software_and_Data_Integrity_Failures + subcategory: + - audit + likelihood: LOW + impact: LOW + languages: [go] + severity: WARNING + patterns: + - pattern-inside: | + import "github.com/dgrijalva/jwt-go" + ... + - pattern: | + $JWT.ParseUnverified(...) +- id: go.jwt-go.security.jwt-none-alg.jwt-go-none-algorithm + message: >- + Detected use of the 'none' algorithm in a JWT token. + The 'none' algorithm assumes the integrity of the token has already + been verified. This would allow a malicious actor to forge a JWT token + that will automatically be verified. Do not explicitly use the 'none' + algorithm. Instead, use an algorithm such as 'HS256'. + metadata: + cwe: + - 'CWE-327: Use of a Broken or Risky Cryptographic Algorithm' + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + source-rule-url: https://semgrep.dev/blog/2020/hardcoded-secrets-unverified-tokens-and-other-common-jwt-mistakes/ + category: security + technology: + - jwt + confidence: HIGH + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - audit + likelihood: LOW + impact: LOW + languages: [go] + severity: ERROR + patterns: + - pattern-either: + - pattern-inside: | + import "github.com/golang-jwt/jwt" + ... + - pattern-inside: | + import "github.com/dgrijalva/jwt-go" + ... + - pattern-either: + - pattern: | + jwt.SigningMethodNone + - pattern: jwt.UnsafeAllowNoneSignatureType +- id: go.jwt-go.security.jwt.hardcoded-jwt-key + message: >- + A hard-coded credential was detected. It is not recommended to store credentials in source-code, + as this risks secrets + being leaked and used by either an internal or external malicious adversary. It is recommended to + use environment variables to securely provide credentials or retrieve credentials from a secure + vault or HSM (Hardware Security Module). + options: + interfile: true + metadata: + cwe: + - 'CWE-798: Use of Hard-coded Credentials' + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + owasp: + - A07:2021 - Identification and Authentication Failures + category: security + technology: + - jwt + - secrets + confidence: MEDIUM + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: HIGH + impact: MEDIUM + interfile: true + severity: WARNING + languages: [go] + mode: taint + pattern-sources: + - patterns: + - pattern-inside: | + []byte("$F") + pattern-sinks: + - patterns: + - pattern-either: + - pattern-inside: | + $TOKEN.SignedString($F) + - focus-metavariable: $F +- id: go.lang.best-practice.channel-guarded-with-mutex.channel-guarded-with-mutex + pattern-either: + - pattern: | + $MUX.Lock() + $VALUE <- $CHANNEL + $MUX.Unlock() + - pattern: | + $MUX.Lock() + $VALUE = <- $CHANNEL + $MUX.Unlock() + message: >- + Detected a channel guarded with a mutex. Channels already have + an internal mutex, so this is unnecessary. Remove the mutex. + See https://hackmongo.com/page/golang-antipatterns/#guarded-channel + for more information. + languages: [go] + severity: WARNING + metadata: + category: best-practice + technology: + - go +- id: go.lang.best-practice.hidden-goroutine.hidden-goroutine + patterns: + - pattern-not: | + func $FUNC(...) { + go func() { + ... + }(...) + $MORE + } + - pattern: | + func $FUNC(...) { + go func() { + ... + }(...) + } + message: >- + Detected a hidden goroutine. Function invocations are expected to synchronous, + and this function will execute asynchronously because all it does is call a + goroutine. Instead, remove the internal goroutine and call the function using + 'go'. + languages: [go] + severity: WARNING + metadata: + category: best-practice + technology: + - go +- id: go.lang.correctness.looppointer.exported_loop_pointer + message: >- + `$VALUE` is a loop pointer that may be exported from the loop. This pointer is + shared between loop iterations, so the exported reference will always point to + the last loop value, which is likely unintentional. To fix, copy the pointer to + a new pointer within the loop. + metadata: + references: + - https://github.com/kyoh86/looppointer + category: correctness + technology: + - go + severity: WARNING + languages: + - go + pattern-either: + - pattern: | + for _, $VALUE := range $SOURCE { + <... &($VALUE) ...> + } + - pattern: | + for _, $VALUE := range $SOURCE { + <... func() { <... &$VALUE ...> } ...> + } + - pattern: | + for _, $VALUE := range $SOURCE { + <... $ANYTHING(..., <... &$VALUE ...>, ...) ...> + } +- id: go.lang.correctness.overflow.overflow.integer-overflow-int16 + message: + Detected conversion of the result of a strconv.Atoi command to an int16. This could lead to an integer overflow, + which could possibly result in unexpected behavior and even privilege escalation. Instead, use `strconv.ParseInt`. + languages: [go] + severity: WARNING + patterns: + - pattern: | + $F, $ERR := strconv.Atoi($NUM) + ... + int16($F) + - metavariable-comparison: + metavariable: $NUM + comparison: $NUM > 32767 or $NUM < -32768 + strip: true + metadata: + category: correctness + technology: + - go +- id: go.lang.correctness.overflow.overflow.integer-overflow-int32 + message: + Detected conversion of the result of a strconv.Atoi command to an int32. This could lead to an integer overflow, + which could possibly result in unexpected behavior and even privilege escalation. Instead, use `strconv.ParseInt`. + languages: [go] + severity: WARNING + patterns: + - pattern: | + $F, $ERR := strconv.Atoi($NUM) + ... + int32($F) + - metavariable-comparison: + metavariable: $NUM + comparison: $NUM > 2147483647 or $NUM < -2147483648 + strip: true + metadata: + category: correctness + technology: + - go +- id: go.lang.correctness.permissions.file_permission.incorrect-default-permission + message: + Detected file permissions that are set to more than `0600` (user/owner can read and write). Setting file permissions + to higher than `0600` is most likely unnecessary and violates the principle of least privilege. Instead, set permissions + to be `0600` or less for os.Chmod, os.Mkdir, os.OpenFile, os.MkdirAll, and ioutil.WriteFile + metadata: + cwe: "CWE-276: Incorrect Default Permissions" + source_rule_url: https://github.com/securego/gosec + category: correctness + references: + - https://github.com/securego/gosec/blob/master/rules/fileperms.go + technology: + - go + severity: WARNING + languages: [go] + patterns: + - pattern-either: + - pattern: os.Chmod($NAME, $PERM) + - pattern: os.Mkdir($NAME, $PERM) + - pattern: os.OpenFile($NAME, $FLAG, $PERM) + - pattern: os.MkdirAll($NAME, $PERM) + - pattern: ioutil.WriteFile($NAME, $DATA, $PERM) + - metavariable-comparison: + metavariable: $PERM + comparison: $PERM > 0o600 + base: 8 + - focus-metavariable: + - $PERM + fix: | + 0600 +- id: go.lang.correctness.use-filepath-join.use-filepath-join + languages: + - go + severity: WARNING + message: "`path.Join(...)` always joins using a forward slash. This may cause + issues on Windows or other systems using a different delimiter. Use + `filepath.Join(...)` instead which uses OS-specific path separators." + metadata: + category: correctness + references: + - https://parsiya.net/blog/2019-03-09-path.join-considered-harmful/ + - https://go.dev/src/path/path.go?s=4034:4066#L145 + likelihood: LOW + impact: HIGH + confidence: LOW + subcategory: + - audit + technology: + - go + mode: taint + pattern-sources: + - patterns: + - pattern: | + ($STR : string) + - pattern-not: | + "..." + - patterns: + - pattern-inside: | + import "path" + ... + - pattern: path.$FUNC(...) + - metavariable-regex: + metavariable: $FUNC + regex: ^(Base|Clean|Dir|Split)$ + - patterns: + - pattern-inside: | + import "path/filepath" + ... + - pattern: filepath.$FUNC(...) + - metavariable-regex: + metavariable: $FUNC + regex: ^(Base|Clean|Dir|FromSlash|Glob|Rel|Split|SplitList|ToSlash|VolumeName)$ + pattern-sinks: + - pattern: path.Join(...) + pattern-sanitizers: + - pattern: | + url.Parse(...) + ... + +- id: go.lang.correctness.useless-eqeq.eqeq-is-bad + patterns: + - pattern-not-inside: assert(...) + - pattern-either: + - pattern: $X == $X + - pattern: $X != $X + - pattern-not: 1 == 1 + message: + Detected useless comparison operation `$X == $X` or `$X != $X`. This will always return 'True' or 'False' and therefore + is not necessary. Instead, remove this comparison operation or use another comparison expression that is not deterministic. + languages: [go] + severity: INFO + metadata: + category: correctness + technology: + - go +- id: go.lang.correctness.useless-eqeq.hardcoded-eq-true-or-false + message: + Detected useless if statement. 'if (True)' and 'if (False)' always result in the same behavior, and therefore is + not necessary in the code. Remove the 'if (False)' expression completely or just the 'if (True)' comparison depending + on which expression is in the code. + languages: [go] + severity: INFO + pattern-either: + - pattern: if (true) { ... } + - pattern: if (false) { ... } + metadata: + category: correctness + technology: + - go +- id: go.lang.maintainability.useless-ifelse.useless-if-conditional + message: + Detected an if block that checks for the same condition on both branches (`$X`). The second condition check is + useless as it is the same as the first, and therefore can be removed from the code, + languages: [go] + severity: WARNING + pattern: | + if ($X) { + ... + } else if ($X) { + ... + } + metadata: + category: maintainability + technology: + - go +- id: go.lang.maintainability.useless-ifelse.useless-if-body + pattern: | + if ($X) { + $S + } else { + $S + } + message: + Detected identical statements in the if body and the else body of an if-statement. This will lead to the same code + being executed no matter what the if-expression evaluates to. Instead, remove the if statement. + languages: [go] + severity: WARNING + metadata: + category: maintainability + technology: + - go +- id: go.lang.security.audit.crypto.bad_imports.insecure-module-used + message: >- + The package `net/http/cgi` is on the import blocklist. + The package is vulnerable to httpoxy attacks (CVE-2015-5386). + It is recommended to use `net/http` or a web framework to build a web application instead. + metadata: + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + cwe: + - 'CWE-327: Use of a Broken or Risky Cryptographic Algorithm' + source-rule-url: https://github.com/securego/gosec + references: + - https://godoc.org/golang.org/x/crypto/sha3 + category: security + technology: + - go + confidence: MEDIUM + subcategory: + - audit + likelihood: MEDIUM + impact: MEDIUM + languages: [go] + severity: WARNING + pattern-either: + - patterns: + - pattern-inside: | + import "net/http/cgi" + ... + - pattern: | + cgi.$FUNC(...) +- id: go.lang.security.audit.crypto.insecure_ssh.avoid-ssh-insecure-ignore-host-key + message: >- + Disabled host key verification detected. This allows man-in-the-middle + attacks. Use the 'golang.org/x/crypto/ssh/knownhosts' package to do + host key verification. + See https://skarlso.github.io/2019/02/17/go-ssh-with-host-key-verification/ + to learn more about the problem and how to fix it. + metadata: + cwe: + - 'CWE-322: Key Exchange without Entity Authentication' + owasp: + - A02:2021 - Cryptographic Failures + source-rule-url: https://github.com/securego/gosec + references: + - https://skarlso.github.io/2019/02/17/go-ssh-with-host-key-verification/ + - https://gist.github.com/Skarlso/34321a230cf0245018288686c9e70b2d + category: security + technology: + - go + confidence: MEDIUM + subcategory: + - audit + likelihood: LOW + impact: LOW + languages: [go] + severity: WARNING + pattern: |- + ssh.InsecureIgnoreHostKey() +- id: go.lang.security.audit.crypto.math_random.math-random-used + metadata: + cwe: + - 'CWE-338: Use of Cryptographically Weak Pseudo-Random Number Generator (PRNG)' + owasp: + - A02:2021 - Cryptographic Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Cryptographic_Storage_Cheat_Sheet.html#secure-random-number-generation + category: security + technology: + - go + confidence: MEDIUM + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + message: Do not use `math/rand`. Use `crypto/rand` instead. + languages: [go] + severity: WARNING + patterns: + - pattern-either: + - pattern: | + import $RAND "$MATH" + - pattern: | + import "$MATH" + - metavariable-regex: + metavariable: $MATH + regex: ^(math/rand(\/v[0-9]+)*)$ + - pattern-either: + - pattern-inside: | + ... + rand.$FUNC(...) + - pattern-inside: | + ... + $RAND.$FUNC(...) + - focus-metavariable: + - $MATH + fix: | + crypto/rand +- id: go.lang.security.audit.crypto.missing-ssl-minversion.missing-ssl-minversion + message: >- + `MinVersion` is missing from this TLS configuration. + By default, TLS 1.2 is currently used as the minimum when acting as a client, and TLS 1.0 when acting as a server. + General purpose web applications should default to TLS 1.3 with all other protocols disabled. + Only where it is known that a web server must support legacy clients + with unsupported an insecure browsers (such as Internet Explorer 10), it may be necessary to enable TLS 1.0 to provide support. + Add `MinVersion: tls.VersionTLS13' to the TLS configuration to bump the minimum version to TLS 1.3. + metadata: + cwe: + - 'CWE-327: Use of a Broken or Risky Cryptographic Algorithm' + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + source-rule-url: https://github.com/securego/gosec/blob/master/rules/tls_config.go + references: + - https://golang.org/doc/go1.14#crypto/tls + - https://golang.org/pkg/crypto/tls/#:~:text=MinVersion + - https://www.us-cert.gov/ncas/alerts/TA14-290A + category: security + technology: + - go + confidence: HIGH + subcategory: + - guardrail + likelihood: MEDIUM + impact: LOW + languages: [go] + severity: WARNING + patterns: + - pattern: | + tls.Config{ $...CONF } + - pattern-not: | + tls.Config{..., MinVersion: ..., ...} + fix: | + tls.Config{ $...CONF, MinVersion: tls.VersionTLS13 } + +- id: go.lang.security.audit.crypto.ssl.ssl-v3-is-insecure + message: >- + SSLv3 is insecure because it has known vulnerabilities. + Starting with go1.14, SSLv3 will be removed. Instead, use + 'tls.VersionTLS13'. + metadata: + cwe: + - 'CWE-327: Use of a Broken or Risky Cryptographic Algorithm' + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + source-rule-url: https://github.com/securego/gosec/blob/master/rules/tls_config.go + references: + - https://golang.org/doc/go1.14#crypto/tls + - https://www.us-cert.gov/ncas/alerts/TA14-290A + category: security + technology: + - go + confidence: HIGH + subcategory: + - vuln + likelihood: MEDIUM + impact: LOW + languages: [go] + severity: WARNING + fix-regex: + regex: VersionSSL30 + replacement: VersionTLS13 + pattern: 'tls.Config{..., MinVersion: $TLS.VersionSSL30, ...}' +- id: go.lang.security.audit.crypto.tls.tls-with-insecure-cipher + message: >- + Detected an insecure CipherSuite via the 'tls' module. This suite is considered + weak. + Use the function 'tls.CipherSuites()' to get a list of good cipher suites. + See https://golang.org/pkg/crypto/tls/#InsecureCipherSuites + for why and what other cipher suites to use. + metadata: + cwe: + - 'CWE-327: Use of a Broken or Risky Cryptographic Algorithm' + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + source-rule-url: https://github.com/securego/gosec/blob/master/rules/tls.go + references: + - https://golang.org/pkg/crypto/tls/#InsecureCipherSuites + category: security + technology: + - go + confidence: HIGH + subcategory: + - vuln + likelihood: HIGH + impact: LOW + languages: [go] + severity: WARNING + pattern-either: + - pattern: | + tls.Config{..., CipherSuites: []$TYPE{..., tls.TLS_RSA_WITH_RC4_128_SHA, ...}} + - pattern: | + tls.Config{..., CipherSuites: []$TYPE{..., tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA, ...}} + - pattern: | + tls.Config{..., CipherSuites: []$TYPE{..., tls.TLS_RSA_WITH_AES_128_CBC_SHA256, ...}} + - pattern: | + tls.Config{..., CipherSuites: []$TYPE{..., tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, ...}} + - pattern: | + tls.Config{..., CipherSuites: []$TYPE{..., tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA, ...}} + - pattern: | + tls.Config{..., CipherSuites: []$TYPE{..., tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, ...}} + - pattern: | + tls.Config{..., CipherSuites: []$TYPE{..., tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, ...}} + - pattern: | + tls.Config{..., CipherSuites: []$TYPE{..., tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, ...}} + - pattern: | + tls.CipherSuite{..., TLS_RSA_WITH_RC4_128_SHA, ...} + - pattern: | + tls.CipherSuite{..., TLS_RSA_WITH_3DES_EDE_CBC_SHA, ...} + - pattern: | + tls.CipherSuite{..., TLS_RSA_WITH_AES_128_CBC_SHA256, ...} + - pattern: | + tls.CipherSuite{..., TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, ...} + - pattern: | + tls.CipherSuite{..., TLS_ECDHE_RSA_WITH_RC4_128_SHA, ...} + - pattern: | + tls.CipherSuite{..., TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, ...} + - pattern: | + tls.CipherSuite{..., TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, ...} + - pattern: | + tls.CipherSuite{..., TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, ...} +- id: go.lang.security.audit.crypto.use_of_weak_crypto.use-of-md5 + message: >- + Detected MD5 hash algorithm which is considered insecure. MD5 is not + collision resistant and is therefore not suitable as a cryptographic + signature. Use SHA256 or SHA3 instead. + languages: [go] + severity: WARNING + metadata: + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + cwe: + - 'CWE-328: Use of Weak Hash' + source-rule-url: https://github.com/securego/gosec#available-rules + category: security + technology: + - go + confidence: MEDIUM + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + patterns: + - pattern-inside: | + import "crypto/md5" + ... + - pattern-either: + - pattern: | + md5.New() + - pattern: | + md5.Sum(...) +- id: go.lang.security.audit.crypto.use_of_weak_crypto.use-of-sha1 + message: >- + Detected SHA1 hash algorithm which is considered insecure. SHA1 is not + collision resistant and is therefore not suitable as a cryptographic + signature. Use SHA256 or SHA3 instead. + languages: [go] + severity: WARNING + metadata: + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + cwe: + - 'CWE-328: Use of Weak Hash' + source-rule-url: https://github.com/securego/gosec#available-rules + category: security + technology: + - go + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + patterns: + - pattern-inside: | + import "crypto/sha1" + ... + - pattern-either: + - pattern: | + sha1.New() + - pattern: | + sha1.Sum(...) +- id: go.lang.security.audit.crypto.use_of_weak_crypto.use-of-des + message: >- + Detected DES cipher algorithm which is insecure. The algorithm is + considered weak and has been deprecated. Use AES instead. + languages: [go] + severity: WARNING + metadata: + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + cwe: + - 'CWE-327: Use of a Broken or Risky Cryptographic Algorithm' + source-rule-url: https://github.com/securego/gosec#available-rules + category: security + technology: + - go + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + patterns: + - pattern-inside: | + import "crypto/des" + ... + - pattern-either: + - pattern: | + des.NewTripleDESCipher(...) + - pattern: | + des.NewCipher(...) +- id: go.lang.security.audit.crypto.use_of_weak_crypto.use-of-rc4 + message: >- + Detected RC4 cipher algorithm which is insecure. The algorithm has many + known vulnerabilities. Use AES instead. + languages: [go] + severity: WARNING + metadata: + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + cwe: + - 'CWE-327: Use of a Broken or Risky Cryptographic Algorithm' + source-rule-url: https://github.com/securego/gosec#available-rules + category: security + technology: + - go + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + patterns: + - pattern-inside: | + import "crypto/rc4" + ... + - pattern: |- + rc4.NewCipher(...) +- id: go.lang.security.audit.crypto.use_of_weak_rsa_key.use-of-weak-rsa-key + message: RSA keys should be at least 2048 bits + languages: [go] + severity: WARNING + metadata: + cwe: + - 'CWE-326: Inadequate Encryption Strength' + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + source-rule-url: https://github.com/securego/gosec/blob/master/rules/rsa.go + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Cryptographic_Storage_Cheat_Sheet.html#algorithms + category: security + technology: + - go + confidence: HIGH + subcategory: + - audit + likelihood: HIGH + impact: MEDIUM + patterns: + - pattern-either: + - pattern: | + rsa.GenerateKey(..., $BITS) + - pattern: | + rsa.GenerateMultiPrimeKey(..., $BITS) + - metavariable-comparison: + metavariable: $BITS + comparison: $BITS < 2048 + - focus-metavariable: + - $BITS + fix: | + 2048 +- id: go.lang.security.audit.dangerous-command-write.dangerous-command-write + patterns: + - pattern: | + $CW.Write($BYTE) + - pattern-inside: | + $CW,$ERR := $CMD.StdinPipe() + ... + - pattern-not: | + $CW.Write("...") + - pattern-not: | + $CW.Write([]byte("...")) + - pattern-not: | + $CW.Write([]byte("..."+"...")) + - pattern-not-inside: | + $BYTE = []byte("..."); + ... + - pattern-not-inside: | + $BYTE = []byte("..."+"..."); + ... + - pattern-inside: | + import "os/exec" + ... + message: >- + Detected non-static command inside Write. Audit the input to '$CW.Write'. + If unverified user data can reach this call site, this is a code injection + vulnerability. A malicious actor can inject a malicious script to execute + arbitrary code. + severity: ERROR + languages: [go] + metadata: + cwe: + - "CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')" + category: security + technology: + - go + confidence: LOW + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + references: + - https://owasp.org/Top10/A03_2021-Injection + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH +- id: go.lang.security.audit.dangerous-exec-cmd.dangerous-exec-cmd + patterns: + - pattern-either: + - patterns: + - pattern: | + exec.Cmd {...,Path: $CMD,...} + - pattern-not: | + exec.Cmd {...,Path: "...",...} + - pattern-not-inside: | + $CMD,$ERR := exec.LookPath("..."); + ... + - pattern-not-inside: | + $CMD = "..."; + ... + - patterns: + - pattern: | + exec.Cmd {...,Args: $ARGS,...} + - pattern-not: | + exec.Cmd {...,Args: []string{...},...} + - pattern-not-inside: | + $ARGS = []string{"...",...}; + ... + - pattern-not-inside: | + $CMD = "..."; + ... + $ARGS = []string{$CMD,...}; + ... + - pattern-not-inside: | + $CMD = exec.LookPath("..."); + ... + $ARGS = []string{$CMD,...}; + ... + - patterns: + - pattern: | + exec.Cmd {...,Args: []string{$CMD,...},...} + - pattern-not: | + exec.Cmd {...,Args: []string{"...",...},...} + - pattern-not-inside: | + $CMD,$ERR := exec.LookPath("..."); + ... + - pattern-not-inside: | + $CMD = "..."; + ... + - patterns: + - pattern-either: + - pattern: | + exec.Cmd {...,Args: []string{"=~/(sh|bash|ksh|csh|tcsh|zsh)/","-c",$EXE,...},...} + - patterns: + - pattern: | + exec.Cmd {...,Args: []string{$CMD,"-c",$EXE,...},...} + - pattern-inside: | + $CMD,$ERR := exec.LookPath("=~/(sh|bash|ksh|csh|tcsh|zsh)/"); + ... + - pattern-not: | + exec.Cmd {...,Args: []string{"...","...","...",...},...} + - pattern-not-inside: | + $EXE = "..."; + ... + - pattern-inside: | + import "os/exec" + ... + message: >- + Detected non-static command inside exec.Cmd. Audit the input to 'exec.Cmd'. + If unverified user data can reach this call site, this is a code injection + vulnerability. A malicious actor can inject a malicious script to execute + arbitrary code. + metadata: + cwe: + - "CWE-94: Improper Control of Generation of Code ('Code Injection')" + owasp: + - A03:2021 - Injection + category: security + technology: + - go + confidence: MEDIUM + references: + - https://owasp.org/Top10/A03_2021-Injection + cwe2022-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH + severity: ERROR + languages: [go] +- id: go.lang.security.audit.dangerous-exec-command.dangerous-exec-command + patterns: + - pattern-either: + - patterns: + - pattern-either: + - pattern: | + exec.Command($CMD,...) + - pattern: | + exec.CommandContext($CTX,$CMD,...) + - pattern-not: | + exec.Command("...",...) + - pattern-not: | + exec.CommandContext($CTX,"...",...) + - patterns: + - pattern-either: + - pattern: | + exec.Command("=~/(sh|bash|ksh|csh|tcsh|zsh)/","-c",$CMD,...) + - pattern: | + exec.CommandContext($CTX,"=~/(sh|bash|ksh|csh|tcsh|zsh)/","-c",$CMD,...) + - pattern-not: | + exec.Command("...","...","...",...) + - pattern-not: | + exec.CommandContext($CTX,"...","...","...",...) + - pattern-either: + - pattern: | + exec.Command("=~/\/bin\/env/","=~/(sh|bash|ksh|csh|tcsh|zsh)/","-c",$CMD,...) + - pattern: | + exec.CommandContext($CTX,"=~/\/bin\/env/","=~/(sh|bash|ksh|csh|tcsh|zsh)/","-c",$CMD,...) + - pattern-inside: | + import "os/exec" + ... + - pattern-not-inside: | + $CMD,$ERR := exec.LookPath("..."); + ... + - pattern-not-inside: | + $CMD = "..."; + ... + message: >- + Detected non-static command inside Command. Audit the input to 'exec.Command'. + If unverified user data can reach this call site, this is a code injection + vulnerability. A malicious actor can inject a malicious script to execute + arbitrary code. + metadata: + cwe: + - "CWE-94: Improper Control of Generation of Code ('Code Injection')" + owasp: + - A03:2021 - Injection + category: security + technology: + - go + confidence: LOW + references: + - https://owasp.org/Top10/A03_2021-Injection + cwe2022-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH + severity: ERROR + languages: [go] +- id: go.lang.security.audit.dangerous-syscall-exec.dangerous-syscall-exec + patterns: + - pattern-either: + - patterns: + - pattern: | + syscall.$METHOD($BIN,...) + - pattern-not: | + syscall.$METHOD("...",...) + - pattern-not-inside: | + $BIN,$ERR := exec.LookPath("..."); + ... + - pattern-not-inside: | + $BIN = "..."; + ... + - patterns: + - pattern: | + syscall.$METHOD($BIN,$ARGS,...) + - pattern-not: | + syscall.$METHOD($BIN,[]string{"...",...},...) + - pattern-not-inside: | + $ARGS := []string{"...",...}; + ... + - pattern-not-inside: | + $CMD = "..."; + ... + $ARGS = []string{$CMD,...}; + ... + - pattern-not-inside: | + $CMD,$ERR := exec.LookPath("..."); + ... + $ARGS = []string{$CMD,...}; + ... + - patterns: + - pattern: | + syscall.$METHOD($BIN,[]string{"=~/(sh|bash|ksh|csh|tcsh|zsh)/","-c",$EXE,...},...) + - pattern-not: | + syscall.$METHOD($BIN,[]string{"...","...","...",...},...) + - patterns: + - pattern: | + syscall.$METHOD($BIN,$ARGS,...) + - pattern-either: + - pattern-inside: | + $ARGS := []string{"=~/(sh|bash|ksh|csh|tcsh|zsh)/","-c",$EXE,...}; + ... + - pattern-inside: | + $CMD = "=~/(sh|bash|ksh|csh|tcsh|zsh)/"; + ... + $ARGS = []string{$CMD,"-c",$EXE,...}; + ... + - pattern-inside: | + $CMD,$ERR := exec.LookPath("=~/(sh|bash|ksh|csh|tcsh|zsh)/"); + ... + $ARGS = []string{$CMD,"-c",$EXE,...}; + ... + - pattern-not-inside: | + $ARGS := []string{"...","...","...",...}; + ... + - pattern-not-inside: | + $CMD = "..."; + ... + $ARGS = []string{$CMD,"...","...",...}; + ... + - pattern-not-inside: | + $CMD,$ERR := exec.LookPath("..."); + ... + $ARGS = []string{$CMD,"...","...",...}; + ... + - pattern-inside: | + import "syscall" + ... + - metavariable-regex: + metavariable: $METHOD + regex: (Exec|ForkExec) + message: >- + Detected non-static command inside Exec. Audit the input to 'syscall.Exec'. + If unverified user data can reach this call site, this is a code injection + vulnerability. A malicious actor can inject a malicious script to execute + arbitrary code. + metadata: + cwe: + - "CWE-94: Improper Control of Generation of Code ('Code Injection')" + owasp: + - A03:2021 - Injection + category: security + technology: + - go + confidence: LOW + references: + - https://owasp.org/Top10/A03_2021-Injection + cwe2022-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH + severity: ERROR + languages: [go] +- id: go.lang.security.audit.database.string-formatted-query.string-formatted-query + languages: [go] + message: >- + String-formatted SQL query detected. This could lead to SQL injection if + the string is not sanitized properly. Audit this call to ensure the + SQL is not manipulable by external data. + severity: WARNING + metadata: + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + cwe: + - "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')" + source-rule-url: https://github.com/securego/gosec + category: security + technology: + - go + confidence: LOW + references: + - https://owasp.org/Top10/A03_2021-Injection + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH + patterns: + - metavariable-regex: + metavariable: $OBJ + regex: (?i).*(db|database) + - pattern-not-inside: | + $VAR = "..." + "..." + ... + $OBJ.$SINK(..., $VAR, ...) + - pattern-not: $OBJ.Exec("...") + - pattern-not: $OBJ.ExecContext($CTX, "...") + - pattern-not: $OBJ.Query("...") + - pattern-not: $OBJ.QueryContext($CTX, "...") + - pattern-not: $OBJ.QueryRow("...") + - pattern-not: $OBJ.QueryRow($CTX, "...") + - pattern-not: $OBJ.QueryRowContext($CTX, "...") + - pattern-either: + - pattern: $OBJ.Exec($X + ...) + - pattern: $OBJ.ExecContext($CTX, $X + ...) + - pattern: $OBJ.Query($X + ...) + - pattern: $OBJ.QueryContext($CTX, $X + ...) + - pattern: $OBJ.QueryRow($X + ...) + - pattern: $OBJ.QueryRow($CTX, $X + ...) + - pattern: $OBJ.QueryRowContext($CTX, $X + ...) + - pattern: $OBJ.Exec(fmt.$P("...", ...)) + - pattern: $OBJ.ExecContext($CTX, fmt.$P("...", ...)) + - pattern: $OBJ.Query(fmt.$P("...", ...)) + - pattern: $OBJ.QueryContext($CTX, fmt.$P("...", ...)) + - pattern: $OBJ.QueryRow(fmt.$P("...", ...)) + - pattern: $OBJ.QueryRow($CTX, fmt.$U("...", ...)) + - pattern: $OBJ.QueryRowContext($CTX, fmt.$P("...", ...)) + - patterns: + - pattern-either: + - pattern: $QUERY = fmt.Fprintf($F, "$SQLSTR", ...) + - pattern: $QUERY = fmt.Sprintf("$SQLSTR", ...) + - pattern: $QUERY = fmt.Printf("$SQLSTR", ...) + - pattern: $QUERY = $X + ... + - pattern-either: + - pattern-inside: | + func $FUNC(...) { + ... + $OBJ.Query($QUERY, ...) + ... + } + - pattern-inside: | + func $FUNC(...) { + ... + $OBJ.ExecContext($CTX, $QUERY, ...) + ... + } + - pattern-inside: | + func $FUNC(...) { + ... + $OBJ.Exec($QUERY, ...) + ... + } + - pattern-inside: | + func $FUNC(...) { + ... + $OBJ.QueryRow($CTX, $QUERY) + ... + } + - pattern-inside: | + func $FUNC(...) { + ... + $OBJ.QueryRow($QUERY) + ... + } + - pattern-inside: | + func $FUNC(...) { + ... + $OBJ.QueryContext($CTX, $QUERY) + ... + } + - pattern-inside: | + func $FUNC(...) { + ... + $OBJ.QueryRowContext($CTX, $QUERY, ...) + ... + } + +- id: go.lang.security.audit.md5-used-as-password.md5-used-as-password + languages: [go] + severity: WARNING + message: >- + It looks like MD5 is used as a password hash. MD5 is not considered a + secure password hash because it can be cracked by an attacker in a short + amount of time. Use a suitable password hashing function such as bcrypt. + You can use the `golang.org/x/crypto/bcrypt` package. + options: + interfile: true + metadata: + category: security + technology: + - md5 + references: + - https://tools.ietf.org/id/draft-lvelvindron-tls-md5-sha1-deprecate-01.html + - https://security.stackexchange.com/questions/211/how-to-securely-hash-passwords + - https://github.com/returntocorp/semgrep-rules/issues/1609 + - https://pkg.go.dev/golang.org/x/crypto/bcrypt + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + cwe: + - 'CWE-327: Use of a Broken or Risky Cryptographic Algorithm' + confidence: MEDIUM + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + interfile: true + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - pattern: md5.New + - pattern: md5.Sum + pattern-sinks: + - patterns: + - pattern: $FUNCTION(...) + - metavariable-regex: + metavariable: $FUNCTION + regex: (?i)(.*password.*) +- id: go.lang.security.audit.net.bind_all.avoid-bind-to-all-interfaces + message: >- + Detected a network listener listening on 0.0.0.0 or an empty string. This could unexpectedly expose + the server publicly as it binds to all available interfaces. Instead, specify another IP address + that is not 0.0.0.0 nor the empty string. + languages: [go] + severity: WARNING + metadata: + cwe: + - 'CWE-200: Exposure of Sensitive Information to an Unauthorized Actor' + owasp: + - A01:2021 - Broken Access Control + source-rule-url: https://github.com/securego/gosec + category: security + technology: + - go + confidence: HIGH + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + pattern-either: + - pattern: tls.Listen($NETWORK, "=~/^0.0.0.0:.*$/", ...) + - pattern: net.Listen($NETWORK, "=~/^0.0.0.0:.*$/", ...) + - pattern: tls.Listen($NETWORK, "=~/^:.*$/", ...) + - pattern: net.Listen($NETWORK, "=~/^:.*$/", ...) +- id: go.lang.security.audit.net.cookie-missing-httponly.cookie-missing-httponly + patterns: + - pattern-not-inside: | + http.Cookie{ + ..., + HttpOnly: true, + ..., + } + - pattern: | + http.Cookie{ + ..., + } + message: >- + A session cookie was detected without setting the 'HttpOnly' flag. + The 'HttpOnly' flag for cookies instructs the browser to forbid + client-side scripts from reading the cookie which mitigates XSS + attacks. Set the 'HttpOnly' flag by setting 'HttpOnly' to 'true' + in the Cookie. + metadata: + cwe: + - "CWE-1004: Sensitive Cookie Without 'HttpOnly' Flag" + owasp: + - A05:2021 - Security Misconfiguration + references: + - https://github.com/0c34/govwa/blob/139693e56406b5684d2a6ae22c0af90717e149b8/util/cookie.go + - https://golang.org/src/net/http/cookie.go + category: security + technology: + - go + confidence: MEDIUM + subcategory: + - vuln + likelihood: LOW + impact: LOW + fix-regex: + regex: (HttpOnly\s*:\s+)false + replacement: \1true + severity: WARNING + languages: [go] +- id: go.lang.security.audit.net.cookie-missing-secure.cookie-missing-secure + patterns: + - pattern-not-inside: | + http.Cookie{ + ..., + Secure: true, + ..., + } + - pattern: | + http.Cookie{ + ..., + } + message: >- + A session cookie was detected without setting the 'Secure' flag. + The 'secure' flag for cookies prevents the client from transmitting + the cookie over insecure channels such as HTTP. Set the 'Secure' + flag by setting 'Secure' to 'true' in the Options struct. + metadata: + cwe: + - "CWE-614: Sensitive Cookie in HTTPS Session Without 'Secure' Attribute" + owasp: + - A05:2021 - Security Misconfiguration + references: + - https://github.com/0c34/govwa/blob/139693e56406b5684d2a6ae22c0af90717e149b8/util/cookie.go + - https://golang.org/src/net/http/cookie.go + category: security + technology: + - go + confidence: MEDIUM + subcategory: + - vuln + likelihood: LOW + impact: LOW + fix-regex: + regex: (Secure\s*:\s+)false + replacement: \1true + severity: WARNING + languages: [go] +- id: go.lang.security.audit.net.dynamic-httptrace-clienttrace.dynamic-httptrace-clienttrace + message: >- + Detected a potentially dynamic ClientTrace. This occurred because semgrep could + not + find a static definition for '$TRACE'. Dynamic ClientTraces are dangerous because + they deserialize function code to run when certain Request events occur, which + could lead + to code being run without your knowledge. Ensure that your ClientTrace is statically + defined. + metadata: + cwe: + - 'CWE-913: Improper Control of Dynamically-Managed Code Resources' + owasp: + - A01:2021 - Broken Access Control + references: + - https://github.com/returntocorp/semgrep-rules/issues/518 + # Detects when a static ClientTrace is not defined in the same file as + # WithClientTrace. Not a perfect detection, but sufficiently works in a + # scan of ~1k repos: https://dev.massive.ret2.co/triager/filter/1007 + category: security + technology: + - go + confidence: MEDIUM + subcategory: + - vuln + likelihood: LOW + impact: LOW + patterns: + - pattern-not-inside: | + package $PACKAGE + ... + &httptrace.ClientTrace { ... } + ... + - pattern: httptrace.WithClientTrace($ANY, $TRACE) + severity: WARNING + languages: + - go +- id: go.lang.security.audit.net.formatted-template-string.formatted-template-string + message: >- + Found a formatted template string passed to 'template.HTML()'. 'template.HTML()' does not escape + contents. Be absolutely sure there is no user-controlled data in this template. If user data can + reach this template, you may have a XSS vulnerability. + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + references: + - https://golang.org/pkg/html/template/#HTML + category: security + technology: + - go + confidence: MEDIUM + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + languages: [go] + severity: WARNING + patterns: + - pattern-not: template.HTML("..." + "...") + - pattern-either: + - pattern: template.HTML($T + $X, ...) + - pattern: template.HTML(fmt.$P("...", ...), ...) + - pattern: | + $T = "..." + ... + $T = $FXN(..., $T, ...) + ... + template.HTML($T, ...) + - pattern: | + $T = fmt.$P("...", ...) + ... + template.HTML($T, ...) + - pattern: | + $T, $ERR = fmt.$P("...", ...) + ... + template.HTML($T, ...) + - pattern: | + $T = $X + $Y + ... + template.HTML($T, ...) + - pattern: |- + $T = "..." + ... + $OTHER, $ERR = fmt.$P(..., $T, ...) + ... + template.HTML($OTHER, ...) +- id: go.lang.security.audit.net.fs-directory-listing.fs-directory-listing + message: >- + Detected usage of 'http.FileServer' as handler: this allows directory listing + and an attacker could navigate through directories looking for sensitive + files. Be sure to disable directory listing or restrict access to specific + directories/files. + severity: WARNING + languages: + - go + patterns: + - pattern-either: + - patterns: + - pattern-inside: | + $FS := http.FileServer(...) + ... + - pattern-either: + - pattern: | + http.ListenAndServe(..., $FS) + - pattern: | + http.ListenAndServeTLS(..., $FS) + - pattern: | + http.Handle(..., $FS) + - pattern: | + http.HandleFunc(..., $FS) + - patterns: + - pattern: | + http.$FN(..., http.FileServer(...)) + - metavariable-regex: + metavariable: $FN + regex: (ListenAndServe|ListenAndServeTLS|Handle|HandleFunc) + metadata: + category: security + cwe: + - 'CWE-548: Exposure of Information Through Directory Listing' + owasp: + - A06:2017 - Security Misconfiguration + - A01:2021 - Broken Access Control + references: + - https://github.com/OWASP/Go-SCP + - https://cwe.mitre.org/data/definitions/548.html + confidence: MEDIUM + technology: + - go + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM +- id: go.lang.security.audit.net.pprof.pprof-debug-exposure + metadata: + cwe: + - 'CWE-489: Active Debug Code' + owasp: 'A06:2017 - Security Misconfiguration' + source-rule-url: https://github.com/securego/gosec#available-rules + references: + - https://www.farsightsecurity.com/blog/txt-record/go-remote-profiling-20161028/ + category: security + technology: + - go + confidence: LOW + subcategory: + - audit + likelihood: LOW + impact: LOW + message: >- + The profiling 'pprof' endpoint is automatically exposed on /debug/pprof. + This could leak information about the server. + Instead, use `import "net/http/pprof"`. See + https://www.farsightsecurity.com/blog/txt-record/go-remote-profiling-20161028/ + for more information and mitigation. + languages: [go] + severity: WARNING + patterns: + - pattern-inside: | + import _ "net/http/pprof" + ... + - pattern-inside: | + func $ANY(...) { + ... + } + - pattern-not-inside: | + $MUX = http.NewServeMux(...) + ... + http.ListenAndServe($ADDR, $MUX) + - pattern-not: http.ListenAndServe("=~/^localhost.*/", ...) + - pattern-not: http.ListenAndServe("=~/^127[.]0[.]0[.]1.*/", ...) + - pattern: http.ListenAndServe(...) +- id: go.lang.security.audit.net.unescaped-data-in-htmlattr.unescaped-data-in-htmlattr + message: >- + Found a formatted template string passed to 'template. + HTMLAttr()'. 'template.HTMLAttr()' does not escape contents. Be absolutely sure there is no user-controlled + data in this template or validate and sanitize the data before passing it into the template. + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + references: + - https://golang.org/pkg/html/template/#HTMLAttr + category: security + technology: + - go + confidence: LOW + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + languages: [go] + severity: WARNING + pattern-either: + - pattern: template.HTMLAttr($T + $X, ...) + - pattern: template.HTMLAttr(fmt.$P("...", ...), ...) + - pattern: | + $T = "..." + ... + $T = $FXN(..., $T, ...) + ... + template.HTMLAttr($T, ...) + - pattern: | + $T = fmt.$P("...", ...) + ... + template.HTMLAttr($T, ...) + - pattern: | + $T, $ERR = fmt.$P("...", ...) + ... + template.HTMLAttr($T, ...) + - pattern: | + $T = $X + $Y + ... + template.HTMLAttr($T, ...) + - pattern: |- + $T = "..." + ... + $OTHER, $ERR = fmt.$P(..., $T, ...) + ... + template.HTMLAttr($OTHER, ...) +- id: go.lang.security.audit.net.unescaped-data-in-js.unescaped-data-in-js + message: >- + Found a formatted template string passed to 'template.JS()'. + 'template.JS()' does not escape contents. Be absolutely sure + there is no user-controlled data in this template. + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + references: + - https://golang.org/pkg/html/template/#JS + category: security + technology: + - go + confidence: LOW + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + languages: [go] + severity: WARNING + pattern-either: + - pattern: template.JS($T + $X, ...) + - pattern: template.JS(fmt.$P("...", ...), ...) + - pattern: | + $T = "..." + ... + $T = $FXN(..., $T, ...) + ... + template.JS($T, ...) + - pattern: | + $T = fmt.$P("...", ...) + ... + template.JS($T, ...) + - pattern: | + $T, $ERR = fmt.$P("...", ...) + ... + template.JS($T, ...) + - pattern: | + $T = $X + $Y + ... + template.JS($T, ...) + - pattern: | + $T = "..." + ... + $OTHER, $ERR = fmt.$P(..., $T, ...) + ... + template.JS($OTHER, ...) +- id: go.lang.security.audit.net.unescaped-data-in-url.unescaped-data-in-url + message: >- + Found a formatted template string passed to 'template.URL()'. + 'template.URL()' does not escape contents, and this could result in XSS (cross-site scripting) and + therefore confidential data being stolen. Sanitize data coming into this function or make sure that no + user-controlled input is coming into the function. + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + references: + - https://golang.org/pkg/html/template/#URL + category: security + technology: + - go + confidence: LOW + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + languages: [go] + severity: WARNING + pattern-either: + - pattern: template.URL($T + $X, ...) + - pattern: template.URL(fmt.$P("...", ...), ...) + - pattern: | + $T = "..." + ... + $T = $FXN(..., $T, ...) + ... + template.URL($T, ...) + - pattern: | + $T = fmt.$P("...", ...) + ... + template.URL($T, ...) + - pattern: | + $T, $ERR = fmt.$P("...", ...) + ... + template.URL($T, ...) + - pattern: | + $T = $X + $Y + ... + template.URL($T, ...) + - pattern: |- + $T = "..." + ... + $OTHER, $ERR = fmt.$P(..., $T, ...) + ... + template.URL($OTHER, ...) +- id: go.lang.security.audit.net.use-tls.use-tls + pattern: http.ListenAndServe($ADDR, $HANDLER) + fix: http.ListenAndServeTLS($ADDR, certFile, keyFile, $HANDLER) + metadata: + cwe: + - 'CWE-319: Cleartext Transmission of Sensitive Information' + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + references: + - https://golang.org/pkg/net/http/#ListenAndServeTLS + category: security + technology: + - go + confidence: MEDIUM + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + message: >- + Found an HTTP server without TLS. Use 'http.ListenAndServeTLS' instead. + See https://golang.org/pkg/net/http/#ListenAndServeTLS for more information. + languages: [go] + severity: WARNING +- id: go.lang.security.audit.net.wip-xss-using-responsewriter-and-printf.wip-xss-using-responsewriter-and-printf + patterns: + - pattern-inside: | + func $FUNC(..., $W http.ResponseWriter, ...) { + ... + var $TEMPLATE = "..." + ... + $W.Write([]byte(fmt.$PRINTF($TEMPLATE, ...)), ...) + ... + } + - pattern-either: + - pattern: | + $PARAMS = r.URL.Query() + ... + $DATA, $ERR := $PARAMS[...] + ... + $INTERM = $ANYTHING(..., $DATA, ...) + ... + $W.Write([]byte(fmt.$PRINTF(..., $INTERM, ...))) + - pattern: | + $PARAMS = r.URL.Query() + ... + $DATA, $ERR := $PARAMS[...] + ... + $INTERM = $DATA[...] + ... + $W.Write([]byte(fmt.$PRINTF(..., $INTERM, ...))) + - pattern: | + $DATA, $ERR := r.URL.Query()[...] + ... + $INTERM = $DATA[...] + ... + $W.Write([]byte(fmt.$PRINTF(..., $INTERM, ...))) + - pattern: | + $DATA, $ERR := r.URL.Query()[...] + ... + $INTERM = $ANYTHING(..., $DATA, ...) + ... + $W.Write([]byte(fmt.$PRINTF(..., $INTERM, ...))) + - pattern: | + $PARAMS = r.URL.Query() + ... + $DATA, $ERR := $PARAMS[...] + ... + $W.Write([]byte(fmt.$PRINTF(..., $DATA, ...))) + message: >- + Found data going from url query parameters into formatted data written to ResponseWriter. + This could be XSS and should not be done. If you must do this, ensure your data + is + sanitized or escaped. + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + category: security + technology: + - go + confidence: MEDIUM + references: + - https://owasp.org/Top10/A03_2021-Injection + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: LOW + impact: MEDIUM + severity: WARNING + languages: + - go +- id: go.lang.security.audit.reflect-makefunc.reflect-makefunc + message: >- + 'reflect.MakeFunc' detected. This will sidestep protections that are + normally afforded by Go's type system. Audit this call and be sure that + user input cannot be used to affect the code generated by MakeFunc; + otherwise, you will have a serious security vulnerability. + metadata: + owasp: + - A01:2021 - Broken Access Control + cwe: + - 'CWE-913: Improper Control of Dynamically-Managed Code Resources' + category: security + technology: + - go + confidence: LOW + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + severity: ERROR + pattern: reflect.MakeFunc(...) + languages: + - go +- id: go.lang.security.audit.sqli.gosql-sqli.gosql-sqli + patterns: + - pattern-either: + - patterns: + - pattern: $DB.$METHOD(...,$QUERY,...) + - pattern-either: + - pattern-inside: | + $QUERY = $X + $Y + ... + - pattern-inside: | + $QUERY += $X + ... + - pattern-inside: | + $QUERY = fmt.Sprintf("...", $PARAM1, ...) + ... + - pattern-not-inside: | + $QUERY += "..." + ... + - pattern-not-inside: | + $QUERY = "..." + "..." + ... + - pattern: $DB.$METHOD(..., $X + $Y, ...) + - pattern: $DB.$METHOD(..., fmt.Sprintf("...", $PARAM1, ...), ...) + - pattern-either: + - pattern-inside: | + $DB, ... = sql.Open(...) + ... + - pattern-inside: | + func $FUNCNAME(..., $DB *sql.DB, ...) { + ... + } + - pattern-not: $DB.$METHOD(..., "..." + "...", ...) + - metavariable-regex: + metavariable: $METHOD + regex: ^(Exec|ExecContent|Query|QueryContext|QueryRow|QueryRowContext)$ + languages: + - go + message: >- + Detected string concatenation with a non-literal variable in a "database/sql" + Go SQL statement. This could lead to SQL injection if the variable is user-controlled + and not properly sanitized. In order to prevent SQL injection, + use parameterized queries or prepared statements instead. + You can use prepared statements with the 'Prepare' and 'PrepareContext' calls. + metadata: + cwe: + - "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')" + references: + - https://golang.org/pkg/database/sql/ + category: security + technology: + - go + confidence: LOW + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: LOW + impact: HIGH + severity: ERROR +- id: go.lang.security.audit.sqli.pg-orm-sqli.pg-orm-sqli + patterns: + - pattern-inside: | + import ( + ... + "$IMPORT" + ) + ... + - metavariable-regex: + metavariable: $IMPORT + regex: .*go-pg + - pattern-either: + - patterns: + - pattern: $DB.$METHOD(...,$QUERY,...) + - pattern-either: + - pattern-inside: | + $QUERY = $X + $Y + ... + - pattern-inside: | + $QUERY += $X + ... + - pattern-inside: | + $QUERY = fmt.Sprintf("...", $PARAM1, ...) + ... + - pattern-not-inside: | + $QUERY += "..." + ... + - pattern-not-inside: | + $QUERY = "..." + "..." + ... + - pattern: | + $DB.$INTFUNC1(...).$METHOD(..., $X + $Y, ...).$INTFUNC2(...) + - pattern: | + $DB.$METHOD(..., fmt.Sprintf("...", $PARAM1, ...), ...) + - pattern-inside: | + $DB = pg.Connect(...) + ... + - pattern-inside: | + func $FUNCNAME(..., $DB *pg.DB, ...) { + ... + } + - pattern-not-inside: | + $QUERY = fmt.Sprintf("...", ...,"...", ...) + ... + - pattern-not-inside: | + $QUERY += "..." + ... + - pattern-not: $DB.$METHOD(...,"...",...) + - pattern-not: | + $DB.$INTFUNC1(...).$METHOD(..., "...", ...).$INTFUNC2(...) + - pattern-not-inside: | + $QUERY = "..." + "..." + - pattern-not: | + "..." + - pattern-not: path.Join(...) + - pattern-not: filepath.Join(...) + - metavariable-regex: + metavariable: $METHOD + regex: ^(Where|WhereOr|Join|GroupExpr|OrderExpr|ColumnExpr)$ + languages: + - go + message: Detected string concatenation with a non-literal variable in a go-pg + ORM SQL statement. This could lead to SQL injection if the variable is + user-controlled and not properly sanitized. In order to prevent SQL + injection, do not use strings concatenated with user-controlled input. + Instead, use parameterized statements. + metadata: + cwe: + - "CWE-89: Improper Neutralization of Special Elements used in an SQL + Command ('SQL Injection')" + references: + - https://pg.uptrace.dev/queries/ + category: security + technology: + - go-pg + confidence: LOW + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: LOW + impact: HIGH + license: Commons Clause License Condition v1.0[LGPL-2.1-only] + severity: ERROR +- id: go.lang.security.audit.sqli.pg-sqli.pg-sqli + languages: + - go + message: >- + Detected string concatenation with a non-literal variable in a go-pg + SQL statement. This could lead to SQL injection if the variable is user-controlled + and not properly sanitized. In order to prevent SQL injection, + use parameterized queries instead of string concatenation. You can use parameterized + queries like so: + '(SELECT ? FROM table, data1)' + metadata: + cwe: + - "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')" + references: + - https://pg.uptrace.dev/ + - https://pkg.go.dev/github.com/go-pg/pg/v10 + category: security + technology: + - go-pg + confidence: LOW + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: LOW + impact: HIGH + severity: ERROR + patterns: + - pattern-either: + - patterns: + - pattern: | + $DB.$METHOD(...,$QUERY,...) + - pattern-either: + - pattern-inside: | + $QUERY = $X + $Y + ... + - pattern-inside: | + $QUERY += $X + ... + - pattern-inside: | + $QUERY = fmt.Sprintf("...", $PARAM1, ...) + ... + - pattern-not-inside: | + $QUERY += "..." + ... + - pattern-not-inside: | + $QUERY = "..." + "..." + ... + - pattern: $DB.$METHOD(..., $X + $Y, ...) + - pattern: $DB.$METHOD(..., fmt.Sprintf("...", $PARAM1, ...), ...) + - pattern-either: + - pattern-inside: | + $DB = pg.Connect(...) + ... + - pattern-inside: | + func $FUNCNAME(..., $DB *pg.DB, ...) { + ... + } + - pattern-not: $DB.$METHOD(..., "..." + "...", ...) + - metavariable-regex: + metavariable: $METHOD + regex: ^(Exec|ExecContext|ExecOne|ExecOneContext|Query|QueryOne|QueryContext|QueryOneContext)$ +- id: go.lang.security.audit.sqli.pgx-sqli.pgx-sqli + languages: + - go + message: >- + Detected string concatenation with a non-literal variable in a pgx + Go SQL statement. This could lead to SQL injection if the variable is user-controlled + and not properly sanitized. In order to prevent SQL injection, + use parameterized queries instead. You can use parameterized queries like so: + (`SELECT $1 FROM table`, `data1) + metadata: + cwe: + - "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')" + references: + - https://github.com/jackc/pgx + - https://pkg.go.dev/github.com/jackc/pgx/v4#hdr-Connection_Pool + category: security + technology: + - pgx + confidence: LOW + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: LOW + impact: HIGH + patterns: + - pattern-either: + - patterns: + - pattern: $DB.$METHOD(...,$QUERY,...) + - pattern-either: + - pattern-inside: | + $QUERY = $X + $Y + ... + - pattern-inside: | + $QUERY += $X + ... + - pattern-inside: | + $QUERY = fmt.Sprintf("...", $PARAM1, ...) + ... + - pattern-not-inside: | + $QUERY += "..." + ... + - pattern-not-inside: | + $QUERY = "..." + "..." + ... + - pattern: $DB.$METHOD(..., $X + $Y, ...) + - pattern: $DB.$METHOD(..., fmt.Sprintf("...", $PARAM1, ...), ...) + - pattern-either: + - pattern-inside: | + $DB, ... = pgx.Connect(...) + ... + - pattern-inside: | + $DB, ... = pgx.NewConnPool(...) + ... + - pattern-inside: | + $DB, ... = pgx.ConnectConfig(...) + ... + - pattern-inside: | + func $FUNCNAME(..., $DB *pgx.Conn, ...) { + ... + } + - pattern-not: $DB.$METHOD(..., "..." + "...", ...) + - metavariable-regex: + metavariable: $METHOD + regex: ^(Exec|ExecEx|Query|QueryEx|QueryRow|QueryRowEx)$ + severity: ERROR +- id: go.lang.security.audit.unsafe-reflect-by-name.unsafe-reflect-by-name + patterns: + - pattern-either: + - pattern: | + $SMTH.MethodByName($NAME,...) + - pattern: | + $SMTH.FieldByName($NAME,...) + - pattern-not: | + $SMTH.MethodByName("...",...) + - pattern-not: | + $SMTH.FieldByName("...",...) + - pattern-inside: | + import "reflect" + ... + message: >- + If an attacker can supply values that the application then uses to determine which + method or field to invoke, + the potential exists for the attacker to create control flow paths through the + application + that were not intended by the application developers. + This attack vector may allow the attacker to bypass authentication or access control + checks + or otherwise cause the application to behave in an unexpected manner. + metadata: + cwe: + - "CWE-470: Use of Externally-Controlled Input to Select Classes or Code ('Unsafe Reflection')" + owasp: + - A03:2021 - Injection + category: security + technology: + - go + confidence: LOW + references: + - https://owasp.org/Top10/A03_2021-Injection + subcategory: + - audit + likelihood: LOW + impact: LOW + severity: WARNING + languages: + - go +- id: go.lang.security.audit.unsafe.use-of-unsafe-block + message: >- + Using the unsafe package in Go gives you low-level memory management and many of the strengths of + the C language, but also steps around the type safety of Go and can lead to buffer overflows and + possible arbitrary code execution by an attacker. + Only use this package if you absolutely know what you're doing. + languages: [go] + severity: WARNING + metadata: + cwe: + - 'CWE-242: Use of Inherently Dangerous Function' + source_rule_url: https://github.com/securego/gosec/blob/master/rules/unsafe.go + category: security + technology: + - go + confidence: LOW + references: + - https://cwe.mitre.org/data/definitions/242.html + subcategory: + - audit + likelihood: LOW + impact: LOW + pattern: unsafe.$FUNC(...) +- id: go.lang.security.audit.xss.import-text-template.import-text-template + message: >- + When working with web applications that involve rendering user-generated + content, it's important to properly escape any HTML content to prevent + Cross-Site Scripting (XSS) attacks. In Go, the `text/template` package does + not automatically escape HTML content, which can leave your application + vulnerable to these types of attacks. To mitigate this risk, it's + recommended to use the `html/template` package instead, which provides + built-in functionality for HTML escaping. By using `html/template` to render + your HTML content, you can help to ensure that your web application is more + secure and less susceptible to XSS vulnerabilities. + metadata: + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + references: + - https://www.veracode.com/blog/secure-development/use-golang-these-mistakes-could-compromise-your-apps-security + category: security + technology: + - go + confidence: LOW + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: LOW + severity: WARNING + patterns: + - pattern: | + import "$IMPORT" + - metavariable-regex: + metavariable: $IMPORT + regex: ^(text/template)$ + - focus-metavariable: $IMPORT + fix: | + html/template + languages: + - go +- id: go.lang.security.audit.xss.no-direct-write-to-responsewriter.no-direct-write-to-responsewriter + languages: + - go + message: >- + Detected directly writing or similar in 'http.ResponseWriter.write()'. + This bypasses HTML escaping that prevents cross-site scripting + vulnerabilities. Instead, use the 'html/template' package + and render data using 'template.Execute()'. + metadata: + category: security + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + license: Commons Clause License Condition v1.0[LGPL-2.1-only] + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + references: + - https://blogtitle.github.io/robn-go-security-pearls-cross-site-scripting-xss/ + technology: + - go + confidence: LOW + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + patterns: + - pattern-either: + - pattern-inside: | + func $HANDLER(..., $WRITER http.ResponseWriter, ...) { + ... + } + - pattern-inside: | + func $HANDLER(..., $WRITER *http.ResponseWriter, ...) { + ... + } + - pattern-inside: | + func(..., $WRITER http.ResponseWriter, ...) { + ... + } + - pattern-either: + - pattern: $WRITER.Write(...) + - pattern: (*$WRITER).Write(...) + - pattern-not: $WRITER.Write([]byte("...")) + severity: WARNING +- id: go.lang.security.audit.xss.no-fprintf-to-responsewriter.no-fprintf-to-responsewriter + message: >- + Detected 'Fprintf' or similar writing to 'http.ResponseWriter'. + This bypasses HTML escaping that prevents cross-site scripting + vulnerabilities. Instead, use the 'html/template' package + to render data to users. + metadata: + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + references: + - https://blogtitle.github.io/robn-go-security-pearls-cross-site-scripting-xss/ + category: security + technology: + - go + confidence: LOW + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + severity: WARNING + patterns: + - pattern-either: + - pattern-inside: | + func $HANDLER(..., $WRITER http.ResponseWriter, ...) { + ... + } + - pattern-inside: | + func(..., $WRITER http.ResponseWriter, ...) { + ... + } + - pattern-not: fmt.$PRINTF($WRITER, "...") + - pattern: fmt.$PRINTF($WRITER, ...) + languages: + - go +- id: go.lang.security.audit.xss.no-interpolation-in-tag.no-interpolation-in-tag + message: >- + Detected template variable interpolation in an HTML tag. + This is potentially vulnerable to cross-site scripting (XSS) + attacks because a malicious actor has control over HTML + but without the need to use escaped characters. Use explicit + tags instead. + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + references: + - https://github.com/golang/go/issues/19669 + - https://blogtitle.github.io/robn-go-security-pearls-cross-site-scripting-xss/ + category: security + technology: + - generic + confidence: LOW + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + languages: + - generic + severity: WARNING + paths: + include: + - '*.html' + - '*.thtml' + - '*.gohtml' + - '*.tmpl' + - '*.tpl' + pattern: <{{ ... }} ... > +- id: go.lang.security.audit.xss.no-interpolation-js-template-string.no-interpolation-js-template-string + message: >- + Detected template variable interpolation in a JavaScript + template string. This is potentially vulnerable to + cross-site scripting (XSS) attacks because a malicious + actor has control over JavaScript but without the need + to use escaped characters. Instead, obtain this variable + outside of the template string and ensure your template + is properly escaped. + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + references: + - https://github.com/golang/go/issues/9200#issuecomment-66100328 + - https://blogtitle.github.io/robn-go-security-pearls-cross-site-scripting-xss/ + category: security + technology: + - generic + confidence: LOW + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + languages: + - generic + severity: WARNING + paths: + include: + - '*.html' + - '*.thtml' + - '*.gohtml' + - '*.tmpl' + - '*.tpl' + patterns: + - pattern-inside: + - pattern: '` ... {{ ... }} ...`' +- id: go.lang.security.audit.xss.no-io-writestring-to-responsewriter.no-io-writestring-to-responsewriter + message: >- + Detected 'io.WriteString()' writing directly to 'http.ResponseWriter'. + This bypasses HTML escaping that prevents cross-site scripting + vulnerabilities. Instead, use the 'html/template' package + to render data to users. + metadata: + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + references: + - https://blogtitle.github.io/robn-go-security-pearls-cross-site-scripting-xss/ + - https://golang.org/pkg/io/#WriteString + category: security + technology: + - go + confidence: LOW + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + severity: WARNING + patterns: + - pattern-either: + - pattern-inside: | + func $HANDLER(..., $WRITER http.ResponseWriter, ...) { + ... + } + - pattern-inside: | + func(..., $WRITER http.ResponseWriter, ...) { + ... + } + - pattern-not: io.WriteString($WRITER, "...") + - pattern: io.WriteString($WRITER, $STRING) + languages: + - go +- id: go.lang.security.audit.xss.no-printf-in-responsewriter.no-printf-in-responsewriter + message: >- + Detected 'printf' or similar in 'http.ResponseWriter.write()'. + This bypasses HTML escaping that prevents cross-site scripting + vulnerabilities. Instead, use the 'html/template' package + to render data to users. + metadata: + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + references: + - https://blogtitle.github.io/robn-go-security-pearls-cross-site-scripting-xss/ + category: security + technology: + - go + confidence: LOW + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + severity: WARNING + patterns: + - pattern-either: + - pattern-inside: | + func $HANDLER(..., $WRITER http.ResponseWriter, ...) { + ... + } + - pattern-inside: | + func(..., $WRITER http.ResponseWriter, ...) { + ... + } + - pattern: | + $WRITER.Write(<... fmt.$PRINTF(...) ...>, ...) + languages: + - go +- id: go.lang.security.audit.xss.template-html-does-not-escape.unsafe-template-type + message: >- + Semgrep could not determine that the argument to 'template.HTML()' + is a constant. 'template.HTML()' and similar does not escape contents. + Be absolutely sure there is no user-controlled data in this + template. If user data can reach this template, you may have + a XSS vulnerability. Instead, do not use this function and + use 'template.Execute()'. + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + references: + - https://golang.org/pkg/html/template/#HTML + - https://github.com/0c34/govwa/blob/139693e56406b5684d2a6ae22c0af90717e149b8/vulnerability/xss/xss.go#L33 + category: security + technology: + - go + confidence: LOW + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + languages: [go] + severity: WARNING + patterns: + - pattern-not: template.$ANY("..." + "...") + - pattern-not: template.$ANY("...") + - pattern-either: + - pattern: template.HTML(...) + - pattern: template.CSS(...) + - pattern: template.HTMLAttr(...) + - pattern: template.JS(...) + - pattern: template.JSStr(...) + - pattern: template.Srcset(...) + - pattern: template.URL(...) +- id: go.lang.security.audit.xxe.parsing-external-entities-enabled.parsing-external-entities-enabled + patterns: + - pattern-inside: | + import ("github.com/lestrrat-go/libxml2/parser") + ... + - pattern: $PARSER := parser.New(parser.XMLParseNoEnt) + message: >- + Detected enabling of "XMLParseNoEnt", which allows parsing of external entities and can lead to XXE + if user controlled data is parsed by the library. Instead, do not enable "XMLParseNoEnt" or be sure + to adequately sanitize user-controlled data when it is being parsed by this library. + languages: + - go + severity: WARNING + metadata: + category: security + cwe: + - 'CWE-611: Improper Restriction of XML External Entity Reference' + owasp: + - A04:2017 - XML External Entities (XXE) + - A05:2021 - Security Misconfiguration + references: + - https://knowledge-base.secureflag.com/vulnerabilities/xml_injection/xml_entity_expansion_go_lang.html + - https://owasp.org/www-community/vulnerabilities/XML_External_Entity_(XXE)_Processing + technology: + - libxml2 + confidence: LOW + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH +- id: go.lang.security.bad_tmp.bad-tmp-file-creation + message: File creation in shared tmp directory without using ioutil.Tempfile + languages: [go] + severity: WARNING + metadata: + cwe: + - 'CWE-377: Insecure Temporary File' + source-rule-url: https://github.com/securego/gosec + category: security + technology: + - go + confidence: LOW + owasp: + - A01:2021 - Broken Access Control + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + pattern-either: + - pattern: ioutil.WriteFile("=~//tmp/.*$/", ...) + - pattern: os.Create("=~//tmp/.*$/", ...) +- id: go.lang.security.decompression_bomb.potential-dos-via-decompression-bomb + message: >- + Detected a possible denial-of-service via a zip bomb attack. By limiting the max + bytes read, you can mitigate this attack. + `io.CopyN()` can specify a size. + severity: WARNING + languages: [go] + patterns: + - pattern-either: + - pattern: io.Copy(...) + - pattern: io.CopyBuffer(...) + - pattern-either: + - pattern-inside: | + gzip.NewReader(...) + ... + - pattern-inside: | + zlib.NewReader(...) + ... + - pattern-inside: | + zlib.NewReaderDict(...) + ... + - pattern-inside: | + bzip2.NewReader(...) + ... + - pattern-inside: | + flate.NewReader(...) + ... + - pattern-inside: | + flate.NewReaderDict(...) + ... + - pattern-inside: | + lzw.NewReader(...) + ... + - pattern-inside: | + tar.NewReader(...) + ... + - pattern-inside: | + zip.NewReader(...) + ... + - pattern-inside: | + zip.OpenReader(...) + ... + fix-regex: + regex: (.*)(Copy|CopyBuffer)\((.*?),(.*?)(\)|,.*\)) + replacement: \1CopyN(\3, \4, 1024*1024*256) + metadata: + cwe: + - 'CWE-400: Uncontrolled Resource Consumption' + source-rule-url: https://github.com/securego/gosec + references: + - https://golang.org/pkg/io/#CopyN + - https://github.com/securego/gosec/blob/master/rules/decompression-bomb.go + category: security + technology: + - go + confidence: LOW + cwe2022-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM +- id: go.lang.security.filepath-clean-misuse.filepath-clean-misuse + message: >- + `Clean` is not intended to sanitize against path traversal attacks. + This function is for finding the shortest path name equivalent to the given input. + Using `Clean` to sanitize file reads may expose this application to + path traversal attacks, where an attacker could access arbitrary files on the server. + To fix this easily, write this: `filepath.FromSlash(path.Clean("/"+strings.Trim(req.URL.Path, "/")))` + However, a better solution is using the `SecureJoin` function in the package `filepath-securejoin`. + See https://pkg.go.dev/github.com/cyphar/filepath-securejoin#section-readme. + severity: ERROR + languages: [go] + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - pattern: | + ($REQUEST : *http.Request).$ANYTHING + - pattern: | + ($REQUEST : http.Request).$ANYTHING + - metavariable-regex: + metavariable: $ANYTHING + regex: ^(BasicAuth|Body|Cookie|Cookies|Form|FormValue|GetBody|Host|MultipartReader|ParseForm|ParseMultipartForm|PostForm|PostFormValue|Referer|RequestURI|Trailer|TransferEncoding|UserAgent|URL)$ + pattern-sinks: + - patterns: + - pattern-either: + - pattern: filepath.Clean($...INNER) + - pattern: path.Clean($...INNER) + pattern-sanitizers: + - pattern-either: + - pattern: | + "/" + ... + fix: filepath.FromSlash(filepath.Clean("/"+strings.Trim($...INNER, "/"))) + options: + interfile: true + metadata: + references: + - https://pkg.go.dev/path#Clean + - http://technosophos.com/2016/03/31/go-quickly-cleaning-filepaths.html + - https://labs.detectify.com/2021/12/15/zero-day-path-traversal-grafana/ + - https://dzx.cz/2021/04/02/go_path_traversal/ + - https://pkg.go.dev/github.com/cyphar/filepath-securejoin#section-readme + cwe: + - "CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')" + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + category: security + technology: + - go + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + interfile: true +- id: go.lang.security.injection.open-redirect.open-redirect + languages: [ go ] + severity: WARNING + message: An HTTP redirect was found to be crafted from user-input `$REQUEST`. + This can lead to open redirect vulnerabilities, potentially allowing attackers + to redirect users to malicious web sites. It is recommend where possible to + not allow user-input to craft the redirect URL. When user-input is necessary + to craft the request, it is recommended to follow OWASP best practices to + restrict the URL to domains in an allowlist. + options: + interfile: true + metadata: + cwe: + - "CWE-601: URL Redirection to Untrusted Site ('Open Redirect')" + references: + - https://knowledge-base.secureflag.com/vulnerabilities/unvalidated_redirects___forwards/open_redirect_go_lang.html + category: security + technology: + - go + confidence: HIGH + description: "An HTTP redirect was found to be crafted from user-input leading to an open redirect vulnerability" + subcategory: + - vuln + impact: MEDIUM + likelihood: MEDIUM + interfile: true + mode: taint + pattern-sources: + - label: INPUT + patterns: + - pattern-either: + - pattern: | + ($REQUEST : *http.Request).$ANYTHING + - pattern: | + ($REQUEST : http.Request).$ANYTHING + - metavariable-regex: + metavariable: $ANYTHING + regex: ^(BasicAuth|Body|Cookie|Cookies|Form|FormValue|GetBody|Host|MultipartReader|ParseForm|ParseMultipartForm|PostForm|PostFormValue|Referer|RequestURI|Trailer|TransferEncoding|UserAgent|URL)$ + - label: CLEAN + requires: INPUT + patterns: + - pattern-either: + - pattern: | + "$URLSTR" + $INPUT + - patterns: + - pattern-either: + - pattern: fmt.Fprintf($F, "$URLSTR", $INPUT, ...) + - pattern: fmt.Sprintf("$URLSTR", $INPUT, ...) + - pattern: fmt.Printf("$URLSTR", $INPUT, ...) + - metavariable-regex: + metavariable: $URLSTR + regex: .*//[a-zA-Z0-10]+\..* + pattern-sinks: + - requires: INPUT and not CLEAN + patterns: + - pattern: http.Redirect($W, $REQ, $URL, ...) + - focus-metavariable: $URL +- id: go.lang.security.injection.raw-html-format.raw-html-format + languages: [go] + severity: WARNING + message: >- + Detected user input flowing into a manually constructed HTML string. You may be + accidentally bypassing secure methods + of rendering HTML by manually constructing HTML and this could create a cross-site + scripting vulnerability, which could + let attackers steal sensitive user data. Use the `html/template` package which + will safely render HTML instead, or inspect + that the HTML is rendered safely. + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + category: security + technology: + - go + references: + - https://blogtitle.github.io/robn-go-security-pearls-cross-site-scripting-xss/ + license: Commons Clause License Condition v1.0[LGPL-2.1-only] + confidence: MEDIUM + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: HIGH + impact: MEDIUM + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - pattern: | + ($REQUEST : *http.Request).$ANYTHING + - pattern: | + ($REQUEST : http.Request).$ANYTHING + - metavariable-regex: + metavariable: $ANYTHING + regex: ^(BasicAuth|Body|Cookie|Cookies|Form|FormValue|GetBody|Host|MultipartReader|ParseForm|ParseMultipartForm|PostForm|PostFormValue|Referer|RequestURI|Trailer|TransferEncoding|UserAgent|URL)$ + pattern-sanitizers: + - pattern: html.EscapeString(...) + pattern-sinks: + - patterns: + - pattern-either: + - pattern: fmt.Printf("$HTMLSTR", ...) + - pattern: fmt.Sprintf("$HTMLSTR", ...) + - pattern: fmt.Fprintf($W, "$HTMLSTR", ...) + - pattern: '"$HTMLSTR" + ...' + - metavariable-pattern: + metavariable: $HTMLSTR + language: generic + pattern: <$TAG ... +- id: go.lang.security.injection.tainted-sql-string.tainted-sql-string + languages: [go] + message: >- + User data flows into this manually-constructed SQL string. User data + can be safely inserted into SQL strings using prepared statements or an + object-relational mapper (ORM). Manually-constructed SQL strings is a + possible indicator of SQL injection, which could let an attacker steal + or manipulate data from the database. + Instead, use prepared statements (`db.Query("SELECT * FROM t WHERE id = ?", id)`) + or a safe library. + options: + interfile: true + metadata: + cwe: + - "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')" + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + references: + - https://golang.org/doc/database/sql-injection + - https://www.stackhawk.com/blog/golang-sql-injection-guide-examples-and-prevention/ + category: security + technology: + - go + confidence: HIGH + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: HIGH + impact: MEDIUM + interfile: true + mode: taint + severity: ERROR + pattern-sources: + - patterns: + - pattern-either: + - pattern: | + ($REQUEST : *http.Request).$ANYTHING + - pattern: | + ($REQUEST : http.Request).$ANYTHING + - metavariable-regex: + metavariable: $ANYTHING + regex: ^(BasicAuth|Body|Cookie|Cookies|Form|FormValue|GetBody|Host|MultipartReader|ParseForm|ParseMultipartForm|PostForm|PostFormValue|Referer|RequestURI|Trailer|TransferEncoding|UserAgent|URL)$ + pattern-sinks: + - patterns: + - pattern-either: + - patterns: + - pattern-either: + - pattern: | + "$SQLSTR" + ... + - patterns: + - pattern-inside: | + $VAR = "$SQLSTR"; + ... + - pattern: $VAR += ... + - patterns: + - pattern-inside: | + var $SB strings.Builder + ... + - pattern-inside: | + $SB.WriteString("$SQLSTR") + ... + $SB.String(...) + - pattern: | + $SB.WriteString(...) + - metavariable-regex: + metavariable: $SQLSTR + regex: (?i)(select|delete|insert|create|update|alter|drop).* + - patterns: + - pattern-either: + - pattern: fmt.Fprintf($F, "$SQLSTR", ...) + - pattern: fmt.Sprintf("$SQLSTR", ...) + - pattern: fmt.Printf("$SQLSTR", ...) + - metavariable-regex: + metavariable: $SQLSTR + regex: \s*(?i)(select|delete|insert|create|update|alter|drop)\b.*%(v|s|q).* + pattern-sanitizers: + - pattern-either: + - pattern: strconv.Atoi(...) + - pattern: | + ($X: bool) +- id: go.lang.security.injection.tainted-url-host.tainted-url-host + languages: + - go + message: A request was found to be crafted from user-input `$REQUEST`. This can + lead to Server-Side Request Forgery (SSRF) vulnerabilities, potentially + exposing sensitive data. It is recommend where possible to not allow + user-input to craft the base request, but to be treated as part of the + path or query parameter. When user-input is necessary to craft the + request, it is recommended to follow OWASP best practices to prevent + abuse, including using an allowlist. + options: + interfile: true + metadata: + cwe: + - "CWE-918: Server-Side Request Forgery (SSRF)" + owasp: + - A10:2021 - Server-Side Request Forgery (SSRF) + references: + - https://goteleport.com/blog/ssrf-attacks/ + category: security + technology: + - go + license: Commons Clause License Condition v1.0[LGPL-2.1-only] + confidence: HIGH + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + impact: MEDIUM + likelihood: MEDIUM + interfile: true + mode: taint + pattern-sources: + - label: INPUT + patterns: + - pattern-either: + - pattern: | + ($REQUEST : *http.Request).$ANYTHING + - pattern: | + ($REQUEST : http.Request).$ANYTHING + - metavariable-regex: + metavariable: $ANYTHING + regex: ^(BasicAuth|Body|Cookie|Cookies|Form|FormValue|GetBody|Host|MultipartReader|ParseForm|ParseMultipartForm|PostForm|PostFormValue|Referer|RequestURI|Trailer|TransferEncoding|UserAgent|URL)$ + - label: CLEAN + requires: INPUT + patterns: + - pattern-either: + - pattern: | + "$URLSTR" + $INPUT + - patterns: + - pattern-either: + - pattern: fmt.Fprintf($F, "$URLSTR", $INPUT, ...) + - pattern: fmt.Sprintf("$URLSTR", $INPUT, ...) + - pattern: fmt.Printf("$URLSTR", $INPUT, ...) + - metavariable-regex: + metavariable: $URLSTR + regex: .*//[a-zA-Z0-10]+\..* + pattern-sinks: + - requires: INPUT and not CLEAN + patterns: + - pattern-either: + - patterns: + - pattern-either: + - patterns: + - pattern-inside: | + $CLIENT := &http.Client{...} + ... + - pattern: $CLIENT.$METHOD($URL, ...) + - pattern: http.$METHOD($URL, ...) + - metavariable-regex: + metavariable: $METHOD + regex: ^(Get|Head|Post|PostForm)$ + - patterns: + - pattern: | + http.NewRequest("$METHOD", $URL, ...) + - metavariable-regex: + metavariable: $METHOD + regex: ^(GET|HEAD|POST|POSTFORM)$ + - focus-metavariable: $URL + severity: WARNING +- id: go.lang.security.zip.path-traversal-inside-zip-extraction + message: File traversal when extracting zip archive + metadata: + cwe: + - "CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')" + source_rule_url: https://github.com/securego/gosec/issues/205 + category: security + technology: + - go + confidence: LOW + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: LOW + languages: [go] + severity: WARNING + pattern: | + reader, $ERR := zip.OpenReader($ARCHIVE) + ... + for _, $FILE := range reader.File { + ... + path := filepath.Join($TARGET, $FILE.Name) + ... + } +- id: go.otto.security.audit.dangerous-execution.dangerous-execution + message: >- + Detected non-static script inside otto VM. Audit the input to 'VM.Run'. + If unverified user data can reach this call site, this is a code injection + vulnerability. A malicious actor can inject a malicious script to execute + arbitrary code. + metadata: + cwe: + - "CWE-94: Improper Control of Generation of Code ('Code Injection')" + owasp: + - A03:2021 - Injection + category: security + technology: + - otto + - vm + confidence: LOW + references: + - https://owasp.org/Top10/A03_2021-Injection + cwe2022-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH + severity: ERROR + patterns: + - pattern-inside: | + $VM = otto.New(...) + ... + - pattern-not: $VM.Run("...", ...) + - pattern: $VM.Run(...) + languages: + - go +- id: go.template.security.insecure-types.go-insecure-templates + patterns: + - pattern-inside: | + import "html/template" + ... + - pattern-either: + - pattern: var $VAR template.HTML = $EXP + - pattern: var $VAR template.CSS = $EXP + - pattern: var $VAR template.HTMLAttr = $EXP + - pattern: var $VAR template.JS = $EXP + - pattern: var $VAR template.JSStr = $EXP + - pattern: var $VAR template.Srcset = $EXP + message: >- + usage of insecure template types. They are documented as a security risk. See https://golang.org/pkg/html/template/#HTML. + severity: WARNING + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + references: + - https://golang.org/pkg/html/template/#HTML + - https://twitter.com/empijei/status/1275177219011350528 + category: security + technology: + - template + confidence: LOW + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + languages: + - go +- id: go.template.security.ssti.go-ssti + patterns: + - pattern-inside: | + import ("html/template") + ... + - pattern: $TEMPLATE = fmt.Sprintf("...", $ARG, ...) + - patterns: + - pattern-either: + - pattern-inside: | + func $FN(..., $REQ *http.Request, ...){ + ... + } + - pattern-inside: | + func $FN(..., $REQ http.Request, ...){ + ... + } + - pattern-inside: | + func(..., $REQ *http.Request, ...){ + ... + } + - patterns: + - pattern-either: + - pattern-inside: | + $ARG := $REQ.URL.Query().Get(...) + ... + $T, $ERR := $TMPL.Parse($TEMPLATE) + - pattern-inside: | + $ARG := $REQ.Form.Get(...) + ... + $T, $ERR := $TMPL.Parse($TEMPLATE) + - pattern-inside: | + $ARG := $REQ.PostForm.Get(...) + ... + $T, $ERR := $TMPL.Parse($TEMPLATE) + message: >- + A server-side template injection occurs when an attacker is able to use + native template syntax to inject a malicious payload into a template, which is then executed server-side. + When using "html/template" always check that user inputs are validated and sanitized before included + within the template. + languages: [go] + severity: ERROR + metadata: + category: security + cwe: + - 'CWE-1336: Improper Neutralization of Special Elements Used in a Template Engine' + references: + - https://www.onsecurity.io/blog/go-ssti-method-research/ + - http://blog.takemyhand.xyz/2020/05/ssti-breaking-gos-template-engine-to.html + technology: + - go + confidence: MEDIUM + subcategory: + - vuln + likelihood: LOW + impact: HIGH +- id: java.android.best-practice.manifest-security-features.manifest-usescleartexttraffic-true + languages: + - generic + message: >- + The Android manifest is configured to allow non-encrypted connections. + Evaluate if this is necessary for your app, and disable it if appropriate. + This flag is ignored on Android 7 (API 24) and above if a Network Security + Config is present. + metadata: + category: best-practice + license: Commons Clause License Condition v1.0[LGPL-2.1-only] + technology: + - android + references: + - https://developer.android.com/guide/topics/manifest/application-element#usesCleartextTraffic + - https://developer.android.com/training/articles/security-config + patterns: + - pattern: | + android:usesCleartextTraffic="true" + - pattern-not-inside: | + + severity: INFO + paths: + include: + - "*.xml" +- id: java.android.best-practice.manifest-security-features.manifest-usescleartexttraffic-ignored-by-nsc + languages: + - generic + message: >- + Manifest uses both `android:usesCleartextTraffic` and Network Security Config. + The `usesCleartextTraffic` directive is ignored on Android 7 (API 24) and above + if a Network Security Config is present. + metadata: + category: best-practice + license: Commons Clause License Condition v1.0[LGPL-2.1-only] + technology: + - android + references: + - https://developer.android.com/guide/topics/manifest/application-element#usesCleartextTraffic + - https://developer.android.com/training/articles/security-config + patterns: + - pattern-either: + # Need to define both orders, as the generic parser does not know that the order does not matter + - pattern: | + android:usesCleartextTraffic ... android:networkSecurityConfig + - pattern: | + android:networkSecurityConfig ... android:usesCleartextTraffic + - pattern-not-inside: | + + severity: INFO + paths: + include: + - "*.xml" +- id: java.android.best-practice.network-security-config.nsc-allows-plaintext-traffic + languages: + - generic + message: >- + The Network Security Config is set to allow non-encrypted connections. + Evaluate if this is necessary for your app, and disable it if appropriate. + (To hide this warning, set `xmlns:tools="http://schemas.android.com/tools" + tools:ignore="InsecureBaseConfiguration"` as parameters to your + ``) + metadata: + category: best-practice + license: Commons Clause License Condition v1.0[LGPL-2.1-only] + technology: + - android + references: + - https://developer.android.com/training/articles/security-config + - https://www.nowsecure.com/blog/2018/08/15/a-security-analysts-guide-to-network-security-configuration-in-android-p/ + patterns: + - pattern: | + + - pattern-not-inside: | + + # If the config explicitly tells us not to check for insecure configurations, respect that + # (on a best-effort basis due to limitations of how much you can glob in generic parser mode) + - pattern-not-inside: | + ... ... ... ... ... ... ... ... ... ... + severity: INFO + paths: + include: + - '*.xml' +- id: java.android.best-practice.network-security-config.nsc-pinning-without-backup + languages: + - generic + message: >- + Your app uses TLS public key pinning without specifying a backup key. + If you are forced to change TLS keys or CAs on short notice, not + having a backup pin can lead to connectivity issues until you can push + out an update. It is considered best practice to add at least one additional + pin as a backup. + metadata: + category: best-practice + license: Commons Clause License Condition v1.0[LGPL-2.1-only] + technology: + - android + references: + - https://developer.android.com/training/articles/security-config#CertificatePinning + - https://www.nowsecure.com/blog/2018/08/15/a-security-analysts-guide-to-network-security-configuration-in-android-p/ + patterns: + # FIXME: This check will currently not detect cases where there are two pins + # listed, but one of them is inside a - these will be recognized + # as having two or more pins. I don't think detecting these cases while not falsely + # detecting cases where there are three pins, but the middle one is commented out, + # is possible using the generic parser - this would require a specialized XML parser + # that has knowledge about comments etc. + - pattern: | + ... + - pattern-not-inside: | + ......... + - pattern-inside: | + ... ... + - pattern-inside: | + ... ... ... ... ... + - pattern-not-inside: | + + severity: INFO + paths: + include: + - '*.xml' +- id: java.android.best-practice.network-security-config.nsc-pinning-without-expiration + languages: + - generic + message: >- + Your app uses TLS public key pinning without specifying an expiration date. + If your users do not update the app to receive new pins in time, expired or replaced + certificates can lead to connectivity issues until they install an update. + It is considered best practice to set an expiration time, after which the system will + default to trusting system CAs and disregard the pin. + metadata: + category: best-practice + license: Commons Clause License Condition v1.0[LGPL-2.1-only] + technology: + - android + references: + - https://developer.android.com/training/articles/security-config#CertificatePinning + - https://www.nowsecure.com/blog/2018/08/15/a-security-analysts-guide-to-network-security-configuration-in-android-p/ + patterns: + - pattern: | + ... ... ... + - pattern-not-inside: | + ... ... ... + - pattern-inside: | + ... ... ... ... ... + - pattern-not-inside: | + + severity: INFO + paths: + include: + - '*.xml' +- id: java.android.best-practice.network-security-config.nsc-allows-user-ca-certs + languages: + - generic + message: >- + The Network Security Config is set to accept user-installed CAs. + Evaluate if this is necessary for your app, and disable it if appropriate. + (To hide this warning, set `xmlns:tools="http://schemas.android.com/tools" + tools:ignore="AcceptsUserCertificates"` as parameters to your + ``) + metadata: + category: best-practice + license: Commons Clause License Condition v1.0[LGPL-2.1-only] + technology: + - android + references: + - https://developer.android.com/training/articles/security-config + - https://www.nowsecure.com/blog/2018/08/15/a-security-analysts-guide-to-network-security-configuration-in-android-p/ + patterns: + - pattern: | + + - pattern-inside: | + ... ... ... ... + - pattern-not-inside: | + + # If the config explicitly tells us not to check for user CAs, respect that + # (on a best-effort basis due to limitations of how much you can glob in generic parser mode) + - pattern-not-inside: | + ... ... ... ... ... ... ... ... ... ... + severity: WARNING + paths: + include: + - '*.xml' +- id: java.android.best-practice.network-security-config.nsc-allows-user-ca-certs-for-domain + languages: + - generic + message: >- + The Network Security Config is set to accept user-installed CAs for the + domain `$DOMAIN`. + Evaluate if this is necessary for your app, and disable it if appropriate. + (To hide this warning, set `xmlns:tools="http://schemas.android.com/tools" + tools:ignore="AcceptsUserCertificates"` as parameters to your + ``) + metadata: + category: best-practice + license: Commons Clause License Condition v1.0[LGPL-2.1-only] + technology: + - android + references: + - https://developer.android.com/training/articles/security-config + - https://www.nowsecure.com/blog/2018/08/15/a-security-analysts-guide-to-network-security-configuration-in-android-p/ + patterns: + - pattern: | + + - pattern-inside: | + ... ... ... + - pattern-inside: | + ... $DOMAIN ... ... ... + - pattern-not-inside: | + + # If the config explicitly tells us not to check for user CAs, respect that + # (on a best-effort basis due to limitations of how much you can glob in generic parser mode) + - pattern-not-inside: | + ... ... ... ... ... ... ... ... ... ... + severity: WARNING + paths: + include: + - '*.xml' +- id: java.android.security.exported_activity.exported_activity + patterns: + - pattern-not-inside: + - pattern-inside: " \n" + - pattern-either: + - pattern: | + + - pattern: | + ... /> + message: >- + The application exports an activity. Any application on the device can launch the exported activity which may compromise the integrity of your application or its data. + Ensure that any exported activities do not have privileged access to your application's control plane. + languages: + - generic + severity: WARNING + paths: + exclude: + - sources/ + - classes3.dex + - '*.so' + include: + - '*AndroidManifest.xml' + metadata: + category: security + subcategory: + - vuln + cwe: + - 'CWE-926: Improper Export of Android Application Components' + confidence: MEDIUM + likelihood: MEDIUM + impact: MEDIUM + owasp: + - A5:2021 Security Misconfiguration + technology: + - Android + references: + - https://cwe.mitre.org/data/definitions/926.html +- id: java.aws-lambda.security.tainted-sql-string.tainted-sql-string + languages: [java] + severity: ERROR + message: >- + Detected user input used to manually construct a SQL string. This is usually + bad practice because manual construction could accidentally result in a SQL + injection. An attacker could use a SQL injection to steal or modify contents + of the database. Instead, use a parameterized query which is available + by default in most database engines. Alternatively, consider using an + object-relational mapper (ORM) such as Sequelize which will protect your queries. + options: + interfile: true + metadata: + references: + - https://owasp.org/www-community/attacks/SQL_Injection + category: security + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + cwe: + - "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')" + technology: + - aws-lambda + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: HIGH + confidence: MEDIUM + interfile: true + mode: taint + pattern-sources: + - patterns: + - focus-metavariable: $EVENT + - pattern-either: + - pattern: | + $HANDLERTYPE $HANDLER($TYPE $EVENT, com.amazonaws.services.lambda.runtime.Context $CONTEXT) { + ... + } + - pattern: | + $HANDLERTYPE $HANDLER(InputStream $EVENT, OutputStream $OUT, com.amazonaws.services.lambda.runtime.Context $CONTEXT) { + ... + } + pattern-sinks: + - patterns: + - pattern-either: + - pattern: | + "$SQLSTR" + ... + - pattern: | + "$SQLSTR".concat(...) + - patterns: + - pattern-inside: | + StringBuilder $SB = new StringBuilder("$SQLSTR"); + ... + - pattern: $SB.append(...) + - patterns: + - pattern-inside: | + $VAR = "$SQLSTR"; + ... + - pattern: $VAR += ... + - pattern: String.format("$SQLSTR", ...) + - metavariable-regex: + metavariable: $SQLSTR + regex: (?i)(select|delete|insert|create|update|alter|drop)\b + - pattern-not-inside: | + System.out.$PRINTLN(...) +- id: java.aws-lambda.security.tainted-sqli.tainted-sqli + message: >- + Detected SQL statement that is tainted by `$EVENT` object. This could lead to SQL + injection if variables in the SQL statement are not properly sanitized. + Use parameterized SQL queries or properly sanitize user input instead. + languages: [java] + severity: WARNING + mode: taint + pattern-sources: + - patterns: + - focus-metavariable: $EVENT + - pattern-either: + - pattern: | + $HANDLERTYPE $HANDLER($TYPE $EVENT, com.amazonaws.services.lambda.runtime.Context $CONTEXT) { + ... + } + - pattern: | + $HANDLERTYPE $HANDLER(InputStream $EVENT, OutputStream $OUT, com.amazonaws.services.lambda.runtime.Context $CONTEXT) { + ... + } + pattern-sinks: + - patterns: + - pattern-either: + - pattern: | + (java.sql.CallableStatement $STMT) = ...; + - pattern: | + (java.sql.Statement $STMT) = ...; + - pattern: | + (java.sql.PreparedStatement $STMT) = ...; + - pattern: | + $VAR = $CONN.prepareStatement(...) + - pattern: | + $PATH.queryForObject(...); + - pattern: | + (java.util.Map $STMT) = $PATH.queryForMap(...); + - pattern: | + (org.springframework.jdbc.support.rowset.SqlRowSet $STMT) = ...; + - patterns: + - pattern-inside: | + (String $SQL) = "$SQLSTR" + ...; + ... + - pattern: $PATH.$SQLCMD(..., $SQL, ...); + - metavariable-regex: + metavariable: $SQLSTR + regex: (?i)(^SELECT.* | ^INSERT.* | ^UPDATE.*) + - metavariable-regex: + metavariable: $SQLCMD + regex: (execute|query|executeUpdate|batchUpdate) + options: + interfile: true + metadata: + category: security + technology: + - sql + - java + - aws-lambda + cwe: + - "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')" + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + references: + - https://owasp.org/Top10/A03_2021-Injection + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: HIGH + confidence: MEDIUM + interfile: true +- id: java.java-jwt.security.audit.jwt-decode-without-verify.java-jwt-decode-without-verify + message: >- + Detected the decoding of a JWT token without a verify step. + JWT tokens must be verified before use, otherwise the token's + integrity is unknown. This means a malicious actor could forge + a JWT token with any claims. Call '.verify()' before using the token. + metadata: + cwe: + - 'CWE-345: Insufficient Verification of Data Authenticity' + owasp: + - A08:2021 - Software and Data Integrity Failures + source-rule-url: https://semgrep.dev/blog/2020/hardcoded-secrets-unverified-tokens-and-other-common-jwt-mistakes/ + category: security + technology: + - jwt + confidence: MEDIUM + references: + - https://owasp.org/Top10/A08_2021-Software_and_Data_Integrity_Failures + subcategory: + - vuln + likelihood: LOW + impact: HIGH + languages: [java] + severity: WARNING + patterns: + - pattern: | + com.auth0.jwt.JWT.decode(...); + - pattern-not-inside: |- + class $CLASS { + ... + $RETURNTYPE $FUNC (...) { + ... + $VERIFIER.verify(...); + ... + } + } +- id: java.java-jwt.security.jwt-hardcode.java-jwt-hardcoded-secret + message: >- + A hard-coded credential was detected. It is not recommended to store credentials in source-code, + as this risks secrets + being leaked and used by either an internal or external malicious adversary. It is recommended to + use environment variables to securely provide credentials or retrieve credentials from a secure + vault or HSM (Hardware Security Module). + metadata: + cwe: + - 'CWE-798: Use of Hard-coded Credentials' + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + owasp: + - A07:2021 - Identification and Authentication Failures + technology: + - java + - secrets + - jwt + category: security + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: LOW + impact: MEDIUM + confidence: HIGH + languages: [java] + severity: WARNING + patterns: + - pattern-either: + - pattern: | + (Algorithm $ALG) = $ALGO.$HMAC("$Y"); + - pattern: | + $SECRET = "$Y"; + ... + (Algorithm $ALG) = $ALGO.$HMAC($SECRET); + - pattern: | + class $CLASS { + ... + $TYPE $SECRET = "$Y"; + ... + $RETURNTYPE $FUNC (...) { + ... + (Algorithm $ALG) = $ALGO.$HMAC($SECRET); + ... + } + ... + } + - focus-metavariable: $Y + - metavariable-regex: + metavariable: $HMAC + regex: (HMAC384|HMAC256|HMAC512) +- id: java.java-jwt.security.jwt-none-alg.java-jwt-none-alg + message: >- + Detected use of the 'none' algorithm in a JWT token. + The 'none' algorithm assumes the integrity of the token has already + been verified. This would allow a malicious actor to forge a JWT token + that will automatically be verified. Do not explicitly use the 'none' + algorithm. Instead, use an algorithm such as 'HS256'. + metadata: + cwe: + - 'CWE-327: Use of a Broken or Risky Cryptographic Algorithm' + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + source-rule-url: https://semgrep.dev/blog/2020/hardcoded-secrets-unverified-tokens-and-other-common-jwt-mistakes/ + category: security + technology: + - jwt + confidence: HIGH + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - vuln + likelihood: HIGH + impact: MEDIUM + languages: [java] + severity: ERROR + pattern-either: + - pattern: | + $JWT.sign(com.auth0.jwt.algorithms.Algorithm.none()); + - pattern: | + $NONE = com.auth0.jwt.algorithms.Algorithm.none(); + ... + $JWT.sign($NONE); + - pattern: |- + class $CLASS { + ... + $TYPE $NONE = com.auth0.jwt.algorithms.Algorithm.none(); + ... + $RETURNTYPE $FUNC (...) { + ... + $JWT.sign($NONE); + ... + } + ... + } +- id: java.jax-rs.security.insecure-resteasy.insecure-resteasy-deserialization + message: >- + When a Restful webservice endpoint is configured to use wildcard mediaType {*/*} as a value for the + @Consumes annotation, an attacker could abuse the SerializableProvider by sending a HTTP Request + with a Content-Type of application/x-java-serialized-object. The body of that request would be processed + by the SerializationProvider and could contain a malicious payload, which may lead to arbitrary code + execution when calling the $Y.getObject method. + severity: WARNING + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - 'CWE-502: Deserialization of Untrusted Data' + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A08:2017 - Insecure Deserialization + - A08:2021 - Software and Data Integrity Failures + references: + - https://access.redhat.com/blogs/766093/posts/3162112 + subcategory: + - audit + technology: + - jax-rs + languages: + - java + pattern-either: + - pattern: | + @Consumes({"application/x-java-serialized-object"}) + - pattern: | + @Consumes({"*/*"}) + - pattern: | + @Consumes("*/*") + - pattern: | + @Consumes({MediaType.WILDCARD_TYPE}) +- id: java.jax-rs.security.insecure-resteasy.default-resteasy-provider-abuse + message: >- + When a Restful webservice endpoint isn't configured with a @Consumes annotation, an attacker could + abuse the SerializableProvider by sending a HTTP Request with a Content-Type of application/x-java-serialized-object. The + body of that request would be processed by the SerializationProvider and could contain a malicious + payload, which may lead to arbitrary code execution. Instead, add a @Consumes annotation to the function + or class. + severity: WARNING + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + category: security + cwe: + - 'CWE-502: Deserialization of Untrusted Data' + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A08:2017 - Insecure Deserialization + - A08:2021 - Software and Data Integrity Failures + references: + - https://access.redhat.com/blogs/766093/posts/3162112 + subcategory: + - audit + technology: + - jax-rs + languages: + - java + patterns: + - pattern: | + @Path("...") + public $RETURNTYPE $METHOD(...) { ...} + - pattern-not-inside: | + @GET + public $RETURNTYPE $METHOD(...) { ...} + - pattern-not-inside: | + @Path("...") + @Consumes(...) + public $RETURNTYPE $METHOD(...) { ...} + - pattern-not-inside: | + @Consumes(...) + public class $CLASSNAME { ... } +- id: java.jax-rs.security.jax-rs-path-traversal.jax-rs-path-traversal + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - "CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')" + source-rule-url: https://find-sec-bugs.github.io/bugs.htm#PATH_TRAVERSAL_IN + references: + - https://www.owasp.org/index.php/Path_Traversal + category: security + technology: + - jax-rs + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: LOW + impact: LOW + confidence: MEDIUM + message: >- + Detected a potential path traversal. A malicious actor + could control the location of this file, to include going backwards + in the directory with '../'. To address this, ensure that user-controlled + variables in file paths are sanitized. You may also consider using a utility + method such as org.apache.commons.io.FilenameUtils.getName(...) to only + retrieve the file name from the path. + severity: WARNING + languages: + - java + pattern-either: + - pattern: | + $RETURNTYPE $FUNC (..., @PathParam(...) $TYPE $VAR, ...) { + ... + new File(..., $VAR, ...); + ... + } + - pattern: |- + $RETURNTYPE $FUNC (..., @javax.ws.rs.PathParam(...) $TYPE $VAR, ...) { + ... + new File(..., $VAR, ...); + ... + } +- id: java.jboss.security.seam-log-injection.seam-log-injection + patterns: + - pattern: | + $LOG.$INFO($X + $Y,...) + - pattern-either: + - pattern-inside: | + import org.jboss.seam.log.Log; + ... + - pattern-inside: | + org.jboss.seam.log.Log $LOG = ...; + ... + - metavariable-regex: + metavariable: $INFO + regex: (debug|error|fatal|info|trace|warn) + languages: [java] + message: >- + Seam Logging API support an expression language to introduce bean property to log messages. + The expression language can also be the source to unwanted code execution. + In this context, an expression is built with a dynamic value. + The source of the value(s) should be verified to avoid that unfiltered values fall into this risky + code evaluation. + metadata: + cwe: + - "CWE-95: Improper Neutralization of Directives in Dynamically Evaluated Code ('Eval Injection')" + owasp: + - A03:2021 - Injection + source-rule-url: https://find-sec-bugs.github.io/bugs.htm#SEAM_LOG_INJECTION + category: security + technology: + - jboss + confidence: LOW + references: + - https://owasp.org/Top10/A03_2021-Injection + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + severity: ERROR +- id: java.jboss.security.session_sqli.find-sql-string-concatenation + message: >- + In $METHOD, $X is used to construct a SQL query via string concatenation. + languages: [java] + severity: ERROR + pattern-either: + - pattern: | + $RETURN $METHOD(...,String $X,...){ + ... + Session $SESSION = ...; + ... + String $QUERY = ... + $X + ...; + ... + PreparedStatement $PS = $SESSION.connection().prepareStatement($QUERY); + ... + ResultSet $RESULT = $PS.executeQuery(); + ... + } + - pattern: | + $RETURN $METHOD(...,String $X,...){ + ... + String $QUERY = ... + $X + ...; + ... + Session $SESSION = ...; + ... + PreparedStatement $PS = $SESSION.connection().prepareStatement($QUERY); + ... + ResultSet $RESULT = $PS.executeQuery(); + ... + } + metadata: + category: security + technology: + - jboss + confidence: MEDIUM + cwe: + - "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')" + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + references: + - https://owasp.org/Top10/A03_2021-Injection + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: LOW + impact: HIGH +- id: java.jjwt.security.jwt-none-alg.jjwt-none-alg + message: >- + Detected use of the 'none' algorithm in a JWT token. + The 'none' algorithm assumes the integrity of the token has already + been verified. This would allow a malicious actor to forge a JWT token + that will automatically be verified. Do not explicitly use the 'none' + algorithm. Instead, use an algorithm such as 'HS256'. + metadata: + cwe: + - 'CWE-327: Use of a Broken or Risky Cryptographic Algorithm' + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + source-rule-url: https://semgrep.dev/blog/2020/hardcoded-secrets-unverified-tokens-and-other-common-jwt-mistakes/ + asvs: + section: 'V3: Session Management Verification Requirements' + control_id: 3.5.3 Insecue Stateless Session Tokens + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x12-V3-Session-management.md#v35-token-based-session-management + version: '4' + category: security + technology: + - jwt + confidence: LOW + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + languages: [java] + severity: ERROR + patterns: + - pattern: | + io.jsonwebtoken.Jwts.builder(); + - pattern-not-inside: |- + $RETURNTYPE $FUNC(...) { + ... + $JWTS.signWith(...); + ... + } +- id: java.lang.correctness.assignment-comparison.assignment-comparison + message: The value of `$X` is being ignored and will be used in the conditional test + languages: [java] + severity: ERROR + pattern-either: + - pattern: if ($X=true) { ... } + - pattern: if ($X=false) { ... } + metadata: + category: correctness + technology: + - java +- id: java.lang.correctness.eqeq.eqeq + patterns: + - pattern-not-inside: assert $X; + - pattern-not-inside: | + assert $X : $Y; + - pattern-either: + - pattern: $X == $X + - pattern: $X != $X + - pattern-not: 1 == 1 + message: >- + `$X == $X` or `$X != $X` is always true. (Unless the value compared is a float + or double). + To test if `$X` is not-a-number, use `Double.isNaN($X)`. + languages: [java] + severity: ERROR + metadata: + category: correctness + technology: + - java +- id: java.lang.correctness.hardcoded-conditional.hardcoded-conditional + patterns: + - pattern-either: + - pattern: if (true) { ... } + - pattern: if (false) { ... } + - pattern: if ($VAR = true) { ... } + - pattern: if ($VAR = false) { ... } + - pattern: if ($EXPR && false) { ... } + - pattern: if (false && $EXPR) { ... } + - pattern: if ($EXPR || true) { ... } + - pattern: if (true || $EXPR) { ... } + message: This if statement will always have the same behavior and is therefore unnecessary. + languages: [java] + severity: ERROR + metadata: + category: correctness + technology: + - java +- id: java.lang.correctness.no-string-eqeq.no-string-eqeq + languages: [java] + patterns: + - pattern-not: null == (String $Y) + - pattern: $X == (String $Y) + message: >- + Strings should not be compared with '=='. + This is a reference comparison operator. + Use '.equals()' instead. + severity: WARNING + metadata: + category: correctness + technology: + - java +- id: java.lang.security.audit.anonymous-ldap-bind.anonymous-ldap-bind + metadata: + cwe: + - 'CWE-287: Improper Authentication' + owasp: + - A02:2017 - Broken Authentication + - A07:2021 - Identification and Authentication Failures + source-rule-url: https://find-sec-bugs.github.io/bugs.htm#LDAP_ANONYMOUS + category: security + technology: + - java + references: + - https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH + confidence: LOW + message: >- + Detected anonymous LDAP bind. + This permits anonymous users to execute LDAP statements. Consider enforcing + authentication for LDAP. See https://docs.oracle.com/javase/tutorial/jndi/ldap/auth_mechs.html + for more information. + severity: WARNING + pattern: | + $ENV.put($CTX.SECURITY_AUTHENTICATION, "none"); + ... + $DCTX = new InitialDirContext($ENV, ...); + languages: + - java +- id: java.lang.security.audit.bad-hexa-conversion.bad-hexa-conversion + metadata: + cwe: + - 'CWE-704: Incorrect Type Conversion or Cast' + owasp: 'A03:2017 - Sensitive Data Exposure' + source-rule-url: https://find-sec-bugs.github.io/bugs.htm#BAD_HEXA_CONVERSION + category: security + technology: + - java + references: + - https://cwe.mitre.org/data/definitions/704.html + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + message: >- + 'Integer.toHexString()' strips leading zeroes from each byte if read byte-by-byte. + This mistake weakens the hash value computed since it introduces more collisions. + Use 'String.format("%02X", ...)' instead. + severity: WARNING + languages: [java] + pattern: |- + $X $METHOD(...) { + ... + MessageDigest $MD = ...; + ... + $MD.digest(...); + ... + Integer.toHexString(...); + } +- id: java.lang.security.audit.blowfish-insufficient-key-size.blowfish-insufficient-key-size + metadata: + cwe: + - 'CWE-326: Inadequate Encryption Strength' + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + source-rule-url: https://find-sec-bugs.github.io/bugs.htm#BLOWFISH_KEY_SIZE + asvs: + section: V6 Stored Cryptography Verification Requirements + control_id: 6.2.5 Insecure Algorithm + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x14-V6-Cryptography.md#v62-algorithms + version: '4' + category: security + technology: + - java + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - audit + likelihood: HIGH + impact: MEDIUM + confidence: HIGH + message: >- + Using less than 128 bits for Blowfish is considered insecure. Use 128 bits + or more, or switch to use AES instead. + severity: WARNING + languages: + - java + patterns: + - pattern: | + $KEYGEN = KeyGenerator.getInstance("Blowfish"); + ... + $KEYGEN.init($SIZE); + - metavariable-comparison: + metavariable: $SIZE + comparison: $SIZE < 128 +- id: java.lang.security.audit.cbc-padding-oracle.cbc-padding-oracle + message: >- + Using CBC with PKCS5Padding is susceptible to padding oracle attacks. A malicious + actor + could discern the difference between plaintext with valid or invalid padding. + Further, + CBC mode does not include any integrity checks. + Use 'AES/GCM/NoPadding' instead. + metadata: + cwe: + - 'CWE-327: Use of a Broken or Risky Cryptographic Algorithm' + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + source-rule-url: https://find-sec-bugs.github.io/bugs.htm#PADDING_ORACLE + references: + - https://capec.mitre.org/data/definitions/463.html + - https://cheatsheetseries.owasp.org/cheatsheets/Cryptographic_Storage_Cheat_Sheet.html#cipher-modes + - https://find-sec-bugs.github.io/bugs.htm#CIPHER_INTEGRITY + category: security + technology: + - java + subcategory: + - audit + likelihood: HIGH + impact: MEDIUM + confidence: HIGH + severity: WARNING + fix: | + "AES/GCM/NoPadding" + languages: + - java + patterns: + - pattern-inside: Cipher.getInstance("=~/.*\/CBC\/PKCS5Padding/") + - pattern: | + "=~/.*\/CBC\/PKCS5Padding/" +- id: java.lang.security.audit.command-injection-formatted-runtime-call.command-injection-formatted-runtime-call + patterns: + - metavariable-pattern: + metavariable: $RUNTIME + patterns: + - pattern-either: + - pattern: (java.lang.Runtime $R) + - pattern: java.lang.Runtime.getRuntime(...) + - pattern-either: + - pattern: $RUNTIME.exec($X + $Y); + - pattern: $RUNTIME.exec(String.format(...)); + - pattern: $RUNTIME.loadLibrary($X + $Y); + - pattern: $RUNTIME.loadLibrary(String.format(...)); + - patterns: + - pattern-either: + - pattern: | + $RUNTIME.exec("=~/(sh|bash|ksh|csh|tcsh|zsh)/", "-c", $ARG,...) + - pattern: | + $RUNTIME.exec(Arrays.asList("=~/(sh|bash|ksh|csh|tcsh|zsh)/","-c",$ARG,...),...) + - pattern: | + $RUNTIME.exec(new String[]{"=~/(sh|bash|ksh|csh|tcsh|zsh)/","-c",$ARG,...},...) + - patterns: + - pattern-either: + - pattern: | + $RUNTIME.exec($CMD,"-c",$ARG,...) + - pattern: | + $RUNTIME.exec(Arrays.asList($CMD,"-c",$ARG,...),...) + - pattern: | + $RUNTIME.exec(new String[]{$CMD,"-c",$ARG,...},...) + - pattern-inside: | + $CMD = "=~/(sh|bash|ksh|csh|tcsh|zsh)/"; + ... + - patterns: + - pattern-either: + - pattern: | + $RUNTIME.exec($CMD, $EXECUTE, $ARG, ...) + - pattern-inside: | + $CMD = new String[]{"=~/(sh|bash|ksh|csh|tcsh|zsh)/", ...}; + ... + - patterns: + - pattern-either: + - pattern: | + $RUNTIME.exec("=~/(sh|bash|ksh|csh|tcsh|zsh)/", $BASH, $ARG,...) + - pattern: | + $RUNTIME.exec(Arrays.asList("=~/(sh|bash|ksh|csh|tcsh|zsh)/",$BASH,$ARG,...),...) + - pattern: | + $RUNTIME.exec(new String[]{"=~/(sh|bash|ksh|csh|tcsh|zsh)/",$BASH,$ARG,...},...) + - pattern-inside: | + $BASH = new String[]{"=~/(-c)/", ...}; + ... + - pattern-not-inside: | + $ARG = "..."; + ... + - pattern-not: | + $RUNTIME.exec("...","...","...",...) + - pattern-not: | + $RUNTIME.exec(new String[]{"...","...","...",...},...) + - pattern-not: | + $RUNTIME.exec(Arrays.asList("...","...","...",...),...) + message: >- + A formatted or concatenated string was detected as input to a java.lang.Runtime + call. + This is dangerous if a variable is controlled by user input and could result in + a + command injection. Ensure your variables are not controlled by users or sufficiently + sanitized. + metadata: + cwe: + - "CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')" + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + source-rule-url: https://find-sec-bugs.github.io/bugs.htm#COMMAND_INJECTION. + category: security + technology: + - java + references: + - https://owasp.org/Top10/A03_2021-Injection + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH + confidence: LOW + severity: ERROR + languages: + - java +- id: java.lang.security.audit.command-injection-process-builder.command-injection-process-builder + pattern-either: + - patterns: + - pattern: | + new ProcessBuilder($CMD,...) + - pattern-not-inside: | + $CMD = "..."; + ... + - pattern-not-inside: | + $CMD = Arrays.asList("...",...); + ... + - pattern-not-inside: | + $CMD = new String[]{"...",...}; + ... + - pattern-not: | + new ProcessBuilder("...",...) + - pattern-not: | + new ProcessBuilder(new String[]{"...",...},...) + - pattern-not: | + new ProcessBuilder(Arrays.asList("...",...),...) + - patterns: + - pattern: | + $PB.command($CMD,...) + - pattern-inside: | + $TYPE $PB = new ProcessBuilder(...); + ... + - pattern-not-inside: | + $CMD = "..."; + ... + - pattern-not-inside: | + $CMD = Arrays.asList("...",...); + ... + - pattern-not-inside: | + $CMD = new String[]{"...",...}; + ... + - pattern-not: | + $PB.command("...",...) + - pattern-not: | + $PB.command(new String[]{"...",...},...) + - pattern-not: | + $PB.command(Arrays.asList("...",...),...) + - patterns: + - pattern-either: + - pattern: | + new ProcessBuilder("=~/(sh|bash|ksh|csh|tcsh|zsh)/","-c",$ARG,...) + - pattern: | + new ProcessBuilder("cmd","/c",$ARG,...) + - pattern: | + new ProcessBuilder(Arrays.asList("cmd","/c",$ARG,...),...) + - pattern: | + new ProcessBuilder(new String[]{"cmd","/c",$ARG,...},...) + - patterns: + - pattern-either: + - pattern: | + new ProcessBuilder($CMD,"/c",$ARG,...) + - pattern: | + new ProcessBuilder(Arrays.asList($CMD,"/c",$ARG,...),...) + - pattern: | + new ProcessBuilder(new String[]{$CMD,"/c",$ARG,...},...) + - pattern-inside: | + $CMD = "cmd"; + ... + - pattern-not-inside: | + $ARG = "..."; + ... + - pattern-not: | + new ProcessBuilder("...","...","...",...) + - pattern-not: | + new ProcessBuilder(new String[]{"...","...","...",...},...) + - pattern-not: | + new ProcessBuilder(Arrays.asList("...","...","...",...),...) + - patterns: + - pattern-either: + - pattern: | + $PB.command("=~/(sh|bash|ksh|csh|tcsh|zsh)/","-c",$ARG,...) + - pattern: | + $PB.command("cmd","/c",$ARG,...) + - pattern: | + $PB.command(Arrays.asList("=~/(sh|bash|ksh|csh|tcsh|zsh)/","-c",$ARG,...),...) + - pattern: | + $PB.command(Arrays.asList("cmd","/c",$ARG,...),...) + - pattern: | + $PB.command(new String[]{"=~/(sh|bash|ksh|csh|tcsh|zsh)/","-c",$ARG,...},...) + - pattern: | + $PB.command(new String[]{"cmd","/c",$ARG,...},...) + - patterns: + - pattern-either: + - pattern: | + $PB.command($CMD,"-c",$ARG,...) + - pattern: | + $PB.command(Arrays.asList($CMD,"-c",$ARG,...),...) + - pattern: | + $PB.command(new String[]{$CMD,"-c",$ARG,...},...) + - pattern-inside: | + $CMD = "=~/(sh|bash|ksh|csh|tcsh|zsh)/"; + ... + - patterns: + - pattern-either: + - pattern: | + $PB.command($CMD,"/c",$ARG,...) + - pattern: | + $PB.command(Arrays.asList($CMD,"/c",$ARG,...),...) + - pattern: | + $PB.command(new String[]{$CMD,"/c",$ARG,...},...) + - pattern-inside: | + $CMD = "cmd"; + ... + - pattern-inside: | + $TYPE $PB = new ProcessBuilder(...); + ... + - pattern-not-inside: | + $ARG = "..."; + ... + - pattern-not: | + $PB.command("...","...","...",...) + - pattern-not: | + $PB.command(new String[]{"...","...","...",...},...) + - pattern-not: | + $PB.command(Arrays.asList("...","...","...",...),...) + message: >- + A formatted or concatenated string was detected as input to a ProcessBuilder call. + This is dangerous if a variable is controlled by user input and could result in + a + command injection. Ensure your variables are not controlled by users or sufficiently + sanitized. + metadata: + cwe: + - "CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')" + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + category: security + technology: + - java + references: + - https://owasp.org/Top10/A03_2021-Injection + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH + confidence: LOW + severity: ERROR + languages: + - java +- id: java.lang.security.audit.cookie-missing-httponly.cookie-missing-httponly + metadata: + cwe: + - "CWE-1004: Sensitive Cookie Without 'HttpOnly' Flag" + owasp: + - A05:2021 - Security Misconfiguration + source-rule-url: https://find-sec-bugs.github.io/bugs.htm#HTTPONLY_COOKIE + asvs: + section: 'V3: Session Management Verification Requirements' + control_id: 3.4.2 Missing Cookie Attribute + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x12-V3-Session-management.md#v34-cookie-based-session-management + version: '4' + category: security + technology: + - java + references: + - https://owasp.org/Top10/A05_2021-Security_Misconfiguration + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + message: >- + A cookie was detected without setting the 'HttpOnly' flag. The 'HttpOnly' flag + for cookies instructs the browser to forbid client-side scripts from reading the + cookie. Set the 'HttpOnly' flag by calling 'cookie.setHttpOnly(true);' + severity: WARNING + languages: [java] + patterns: + - pattern-not-inside: $COOKIE.setValue(""); ... + - pattern-either: + - pattern: $COOKIE.setHttpOnly(false); + - patterns: + - pattern-not-inside: $COOKIE.setHttpOnly(...); ... + - pattern-not-inside: $COOKIE = ResponseCookie.from(...). ...; ... + - pattern: $RESPONSE.addCookie($COOKIE); +- id: java.lang.security.audit.cookie-missing-secure-flag.cookie-missing-secure-flag + metadata: + cwe: + - "CWE-614: Sensitive Cookie in HTTPS Session Without 'Secure' Attribute" + owasp: + - A05:2021 - Security Misconfiguration + source-rule-url: https://find-sec-bugs.github.io/bugs.htm#INSECURE_COOKIE + asvs: + section: 'V3: Session Management Verification Requirements' + control_id: 3.4.1 Missing Cookie Attribute + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x12-V3-Session-management.md#v34-cookie-based-session-management + version: '4' + category: security + technology: + - java + references: + - https://owasp.org/Top10/A05_2021-Security_Misconfiguration + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + message: >- + A cookie was detected without setting the 'secure' flag. The 'secure' flag + for cookies prevents the client from transmitting the cookie over insecure + channels such as HTTP. Set the 'secure' flag by calling '$COOKIE.setSecure(true);' + severity: WARNING + languages: [java] + patterns: + - pattern-not-inside: $COOKIE.setValue(""); ... + - pattern-either: + - pattern: $COOKIE.setSecure(false); + - patterns: + - pattern-not-inside: $COOKIE.setSecure(...); ... + - pattern-not-inside: $COOKIE = ResponseCookie.from(...). ...; ... + - pattern: $RESPONSE.addCookie($COOKIE); +- id: java.lang.security.audit.crlf-injection-logs.crlf-injection-logs + message: >- + When data from an untrusted source is put into a logger and not neutralized correctly, + an attacker could forge log entries or include malicious content. + metadata: + cwe: + - "CWE-93: Improper Neutralization of CRLF Sequences ('CRLF Injection')" + owasp: + - A03:2021 - Injection + source-rule-url: https://find-sec-bugs.github.io/bugs.htm#CRLF_INJECTION_LOGS + category: security + technology: + - java + references: + - https://owasp.org/Top10/A03_2021-Injection + subcategory: + - vuln + likelihood: LOW + impact: MEDIUM + confidence: MEDIUM + severity: WARNING + languages: [java] + patterns: + # Enumerate possible enclosing scopes that define request and logger + - pattern-either: + # Logger is defined as a field on a class + - patterns: + - pattern-inside: | + class $CLASS { + ... + Logger $LOG = ...; + ... + } + - pattern-either: + - pattern-inside: | + $X $METHOD(...,HttpServletRequest $REQ,...) { + ... + } + - pattern-inside: | + $X $METHOD(...,ServletRequest $REQ,...) { + ... + } + - pattern-inside: | + $X $METHOD(...) { + ... + HttpServletRequest $REQ = ...; + ... + } + - pattern-inside: | + $X $METHOD(...) { + ... + ServletRequest $REQ = ...; + ... + } + - pattern-inside: | + $X $METHOD(...) { + ... + Logger $LOG = ...; + ... + HttpServletRequest $REQ = ...; + ... + } + - pattern-inside: | + $X $METHOD(...) { + ... + Logger $LOG = ...; + ... + ServletRequest $REQ = ...; + ... + } + - pattern-either: + # Enumerate possible injection sites + - pattern: | + String $VAL = $REQ.getParameter(...); + ... + $LOG.$LEVEL(<... $VAL ...>); + - pattern: | + String $VAL = $REQ.getParameter(...); + ... + $LOG.log($LEVEL,<... $VAL ...>); + - pattern: | + $LOG.$LEVEL(<... $REQ.getParameter(...) ...>); + - pattern: | + $LOG.log($LEVEL,<... $REQ.getParameter(...) ...>); +- id: java.lang.security.audit.crypto.des-is-deprecated.des-is-deprecated + message: >- + DES is considered deprecated. AES is the recommended cipher. + Upgrade to use AES. + See https://www.nist.gov/news-events/news/2005/06/nist-withdraws-outdated-data-encryption-standard + for more information. + metadata: + functional-categories: + - 'crypto::search::symmetric-algorithm::javax.crypto' + cwe: + - 'CWE-326: Inadequate Encryption Strength' + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + source-rule-url: https://find-sec-bugs.github.io/bugs.htm#DES_USAGE + asvs: + section: V6 Stored Cryptography Verification Requirements + control_id: 6.2.5 Insecure Algorithm + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x14-V6-Cryptography.md#v62-algorithms + version: '4' + references: + - https://www.nist.gov/news-events/news/2005/06/nist-withdraws-outdated-data-encryption-standard + - https://cheatsheetseries.owasp.org/cheatsheets/Cryptographic_Storage_Cheat_Sheet.html#algorithms + category: security + technology: + - java + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: HIGH + severity: WARNING + patterns: + - pattern-either: + - pattern-inside: $CIPHER.getInstance("=~/DES/.*/") + - pattern-inside: $CIPHER.getInstance("DES") + - pattern-either: + - pattern: | + "=~/DES/.*/" + - pattern: | + "DES" + fix: | + "AES/GCM/NoPadding" + languages: + - java + - kt +- id: java.lang.security.audit.crypto.desede-is-deprecated.desede-is-deprecated + message: >- + Triple DES (3DES or DESede) is considered deprecated. AES is the recommended cipher. + Upgrade to use AES. + metadata: + functional-categories: + - 'crypto::search::symmetric-algorithm::javax.crypto' + cwe: + - 'CWE-326: Inadequate Encryption Strength' + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + source-rule-url: https://find-sec-bugs.github.io/bugs.htm#TDES_USAGE + references: + - https://csrc.nist.gov/News/2017/Update-to-Current-Use-and-Deprecation-of-TDEA + category: security + technology: + - java + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: HIGH + severity: WARNING + patterns: + - pattern-either: + - pattern: | + $CIPHER.getInstance("=~/DESede.*/") + - pattern: | + $CRYPTO.KeyGenerator.getInstance("DES") + languages: + - java + - kt +- id: java.lang.security.audit.crypto.ecb-cipher.ecb-cipher + metadata: + functional-categories: + - 'crypto::search::mode::javax.crypto' + cwe: + - 'CWE-327: Use of a Broken or Risky Cryptographic Algorithm' + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + source-rule-url: https://find-sec-bugs.github.io/bugs.htm#ECB_MODE + category: security + technology: + - java + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: HIGH + message: >- + Cipher in ECB mode is detected. ECB mode produces the same output for the same + input each time + which allows an attacker to intercept and replay the data. Further, ECB mode does + not provide + any integrity checking. See https://find-sec-bugs.github.io/bugs.htm#CIPHER_INTEGRITY. + severity: WARNING + languages: + - java + patterns: + - pattern: | + Cipher $VAR = $CIPHER.getInstance($MODE); + - metavariable-regex: + metavariable: $MODE + regex: .*ECB.* +- id: java.lang.security.audit.crypto.gcm-detection.gcm-detection + metadata: + category: security + functional-categories: + - 'crypto::search::randomness::javax.crypto' + cwe: + - 'CWE-323: Reusing a Nonce, Key Pair in Encryption' + references: + - https://cwe.mitre.org/data/definitions/323.html + technology: + - java + owasp: + - A02:2021 - Cryptographic Failures + subcategory: + - audit + likelihood: MEDIUM + impact: MEDIUM + confidence: LOW + languages: + - java + message: >- + GCM detected, please check that IV/nonce is not reused, an Initialization + Vector (IV) is a nonce used to randomize the encryption, so that even if + multiple messages with identical plaintext are encrypted, the generated + corresponding ciphertexts are different. Unlike the Key, the IV usually + does not need to be secret, rather it is important that it is random and + unique. Certain encryption schemes the IV is exchanged in public as part of + the ciphertext. Reusing same Initialization Vector with the same Key to + encrypt multiple plaintext blocks allows an attacker to compare the + ciphertexts and then, with some assumptions on the content of the + messages, to gain important information about the data being encrypted. + patterns: + - pattern-either: + - pattern: $METHOD.getInstance("AES/GCM/NoPadding",...); + - pattern: new GCMParameterSpec(...); + severity: INFO +- id: java.lang.security.audit.crypto.gcm-nonce-reuse.gcm-nonce-reuse + metadata: + functional-categories: + - 'crypto::search::randomness::javax.crypto' + cwe: + - 'CWE-323: Reusing a Nonce, Key Pair in Encryption' + category: security + source-rule-url: https://www.youtube.com/watch?v=r1awgAl90wM + technology: + - java + owasp: + - A02:2021 - Cryptographic Failures + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: HIGH + languages: + - java + message: 'GCM IV/nonce is reused: encryption can be totally useless' + patterns: + - pattern-either: + - pattern: new GCMParameterSpec(..., "...".getBytes(...), ...); + - pattern: byte[] $NONCE = "...".getBytes(...); ... new GCMParameterSpec(..., $NONCE, ...); + severity: ERROR +- id: java.lang.security.audit.crypto.no-null-cipher.no-null-cipher + patterns: + - pattern-either: + - pattern: new NullCipher(...); + - pattern: new javax.crypto.NullCipher(...); + metadata: + cwe: + - 'CWE-327: Use of a Broken or Risky Cryptographic Algorithm' + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + source-rule-url: https://find-sec-bugs.github.io/bugs.htm#NULL_CIPHER + asvs: + section: V6 Stored Cryptography Verification Requirements + control_id: 6.2.5 Insecure Algorithm + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x14-V6-Cryptography.md#v62-algorithms + version: '4' + category: security + technology: + - java + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: HIGH + message: >- + NullCipher was detected. This will not encrypt anything; + the cipher text will be the same as the plain text. Use + a valid, secure cipher: Cipher.getInstance("AES/CBC/PKCS7PADDING"). + See https://owasp.org/www-community/Using_the_Java_Cryptographic_Extensions + for more information. + severity: WARNING + languages: + - java +- id: java.lang.security.audit.crypto.no-static-initialization-vector.no-static-initialization-vector + message: >- + Initialization Vectors (IVs) for block ciphers should be randomly generated + each time they are used. Using a static IV means the same plaintext + encrypts to the same ciphertext every time, weakening the strength + of the encryption. + metadata: + cwe: + - 'CWE-329: Generation of Predictable IV with CBC Mode' + owasp: + - A02:2021 - Cryptographic Failures + source-rule-url: https://find-sec-bugs.github.io/bugs.htm#STATIC_IV + asvs: + section: V6 Stored Cryptography Verification Requirements + control_id: 6.2.5 Insecure Algorithm + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x14-V6-Cryptography.md#v62-algorithms + version: '4' + references: + - https://cwe.mitre.org/data/definitions/329.html + category: security + technology: + - java + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: HIGH + severity: WARNING + languages: [java] + pattern-either: + - pattern: | + byte[] $IV = { + ... + }; + ... + new IvParameterSpec($IV, ...); + - pattern: | + class $CLASS { + byte[] $IV = { + ... + }; + ... + $METHOD(...) { + ... + new IvParameterSpec($IV, ...); + ... + } + } +- id: java.lang.security.audit.crypto.rsa-no-padding.rsa-no-padding + metadata: + functional-categories: + - 'crypto::search::mode::javax.crypto' + cwe: + - 'CWE-326: Inadequate Encryption Strength' + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + source-rule-url: https://find-sec-bugs.github.io/bugs.htm#RSA_NO_PADDING + references: + - https://rdist.root.org/2009/10/06/why-rsa-encryption-padding-is-critical/ + asvs: + section: V6 Stored Cryptography Verification Requirements + control_id: 6.2.5 Insecure Algorithm + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x14-V6-Cryptography.md#v62-algorithms + version: '4' + category: security + technology: + - java + - kotlin + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: HIGH + message: >- + Using RSA without OAEP mode weakens the encryption. + severity: WARNING + languages: + - java + - kt + pattern: $CIPHER.getInstance("=~/RSA/[Nn][Oo][Nn][Ee]/NoPadding/") +- id: java.lang.security.audit.crypto.ssl.avoid-implementing-custom-digests.avoid-implementing-custom-digests + metadata: + cwe: + - 'CWE-327: Use of a Broken or Risky Cryptographic Algorithm' + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + source-rule-url: https://find-sec-bugs.github.io/bugs.htm#CUSTOM_MESSAGE_DIGEST + asvs: + section: V6 Stored Cryptography Verification Requirements + control_id: 6.2.2 Insecure Custom Algorithm + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x14-V6-Cryptography.md#v62-algorithms + version: '4' + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Cryptographic_Storage_Cheat_Sheet.html#custom-algorithms + category: security + technology: + - java + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + message: >- + Cryptographic algorithms are notoriously difficult to get right. By implementing + a custom message digest, you risk introducing security issues into your program. + Use one of the many sound message digests already available to you: + MessageDigest sha256Digest = MessageDigest.getInstance("SHA256"); + severity: WARNING + languages: [java] + pattern: |- + class $CLASS extends MessageDigest { + ... + } +- id: java.lang.security.audit.crypto.ssl.defaulthttpclient-is-deprecated.defaulthttpclient-is-deprecated + metadata: + cwe: + - 'CWE-326: Inadequate Encryption Strength' + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + source-rule-url: https://find-sec-bugs.github.io/bugs.htm#DEFAULT_HTTP_CLIENT + asvs: + section: V9 Communications Verification Requirements + control_id: 9.1.3 Weak TLS + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x17-V9-Communications.md#v91-client-communications-security-requirements + version: '4' + category: security + technology: + - java + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + message: >- + DefaultHttpClient is deprecated. Further, it does not support connections + using TLS1.2, which makes using DefaultHttpClient a security hazard. + Use HttpClientBuilder instead. + severity: WARNING + languages: [java] + pattern: new DefaultHttpClient(...); + fix-regex: + regex: DefaultHttpClient + replacement: HttpClientBuilder +- id: java.lang.security.audit.crypto.ssl.insecure-hostname-verifier.insecure-hostname-verifier + message: >- + Insecure HostnameVerifier implementation detected. This will accept + any SSL certificate with any hostname, which creates the possibility + for man-in-the-middle attacks. + metadata: + cwe: + - 'CWE-295: Improper Certificate Validation' + owasp: + - A03:2017 - Sensitive Data Exposure + - A07:2021 - Identification and Authentication Failures + source-rule-url: https://find-sec-bugs.github.io/bugs.htm#WEAK_HOSTNAME_VERIFIER + asvs: + section: V9 Communications Verification Requirements + control_id: 9.2.1 Weak TLS + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x17-V9-Communications.md#v92-server-communications-security-requirements + version: '4' + category: security + technology: + - java + references: + - https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + severity: WARNING + languages: [java] + pattern-either: + - pattern: | + class $CLASS implements HostnameVerifier { + ... + public boolean verify(...) { return true; } + } + - pattern: |- + new HostnameVerifier(...){ + public boolean verify(...) { + return true; + } + } + - pattern: import org.apache.http.conn.ssl.NoopHostnameVerifier; +- id: java.lang.security.audit.crypto.ssl.insecure-trust-manager.insecure-trust-manager + metadata: + cwe: + - 'CWE-295: Improper Certificate Validation' + owasp: + - A03:2017 - Sensitive Data Exposure + - A07:2021 - Identification and Authentication Failures + source-rule-url: https://find-sec-bugs.github.io/bugs.htm#WEAK_TRUST_MANAGER + asvs: + section: V9 Communications Verification Requirements + control_id: 9.2.1 Weak TLS + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x17-V9-Communications.md#v92-server-communications-security-requirements + version: '4' + references: + - https://stackoverflow.com/questions/2642777/trusting-all-certificates-using-httpclient-over-https + category: security + technology: + - java + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + message: >- + Detected empty trust manager implementations. This is dangerous because it accepts + any + certificate, enabling man-in-the-middle attacks. Consider using a KeyStore + and TrustManagerFactory instead. + See https://stackoverflow.com/questions/2642777/trusting-all-certificates-using-httpclient-over-https + for more information. + severity: WARNING + languages: [java] + patterns: + - pattern-either: + - pattern-inside: | + class $CLASS implements X509TrustManager { + ... + } + - pattern-inside: | + new X509TrustManager() { + ... + } + - pattern-inside: | + class $CLASS implements X509ExtendedTrustManager { + ... + } + - pattern-inside: | + new X509ExtendedTrustManager() { + ... + } + - pattern-not: public void checkClientTrusted(...) { $SOMETHING; } + - pattern-not: public void checkServerTrusted(...) { $SOMETHING; } + - pattern-either: + - pattern: public void checkClientTrusted(...) {} + - pattern: public void checkServerTrusted(...) {} + - pattern: public X509Certificate[] getAcceptedIssuers(...) { return null; } +- id: java.lang.security.audit.crypto.unencrypted-socket.unencrypted-socket + metadata: + functional-categories: + - 'net::search::crypto-config::java.net' + cwe: + - 'CWE-319: Cleartext Transmission of Sensitive Information' + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + source-rule-url: https://find-sec-bugs.github.io/bugs.htm#UNENCRYPTED_SOCKET + asvs: + section: V6 Stored Cryptography Verification Requirements + control_id: 6.2.5 Insecure Algorithm + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x14-V6-Cryptography.md#v62-algorithms + version: '4' + category: security + technology: + - java + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: HIGH + message: >- + Detected use of a Java socket that is not encrypted. + As a result, the traffic could be read by an attacker intercepting the network traffic. + Use an SSLSocket created by 'SSLSocketFactory' or 'SSLServerSocketFactory' + instead. + severity: WARNING + languages: [java] + pattern-either: + - pattern: new ServerSocket(...) + - pattern: new Socket(...) +- id: java.lang.security.audit.crypto.use-of-aes-ecb.use-of-aes-ecb + pattern: $CIPHER.getInstance("=~/AES/ECB.*/") + metadata: + functional-categories: + - 'crypto::search::mode::javax.crypto' + cwe: + - 'CWE-327: Use of a Broken or Risky Cryptographic Algorithm' + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + category: security + technology: + - java + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + - https://googleprojectzero.blogspot.com/2022/10/rc4-is-still-considered-harmful.html + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: HIGH + message: >- + Use of AES with ECB mode detected. ECB doesn't provide message confidentiality and + is not semantically secure so should not be used. + Instead, use a strong, secure cipher: Cipher.getInstance("AES/CBC/PKCS7PADDING"). + See https://owasp.org/www-community/Using_the_Java_Cryptographic_Extensions + for more information. + severity: WARNING + languages: + - java +- id: java.lang.security.audit.crypto.use-of-blowfish.use-of-blowfish + pattern: $CIPHER.getInstance("Blowfish") + metadata: + functional-categories: + - 'crypto::search::symmetric-algorithm::javax.crypto' + cwe: + - 'CWE-327: Use of a Broken or Risky Cryptographic Algorithm' + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + category: security + technology: + - java + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + - https://googleprojectzero.blogspot.com/2022/10/rc4-is-still-considered-harmful.html + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: HIGH + message: >- + Use of Blowfish was detected. Blowfish uses a 64-bit block size that + makes it vulnerable to birthday attacks, and is therefore considered non-compliant. + Instead, use a strong, secure cipher: Cipher.getInstance("AES/CBC/PKCS7PADDING"). + See https://owasp.org/www-community/Using_the_Java_Cryptographic_Extensions + for more information. + severity: WARNING + languages: + - java +- id: java.lang.security.audit.crypto.use-of-default-aes.use-of-default-aes + pattern-either: + - patterns: + - pattern-either: + - pattern-inside: | + import javax; + ... + - pattern-either: + - pattern: javax.crypto.Cipher.getInstance("AES") + - pattern: (javax.crypto.Cipher $CIPHER).getInstance("AES") + - patterns: + - pattern-either: + - pattern-inside: | + import javax.*; + ... + - pattern-inside: | + import javax.crypto; + ... + - pattern-either: + - pattern: crypto.Cipher.getInstance("AES") + - pattern: (crypto.Cipher $CIPHER).getInstance("AES") + - patterns: + - pattern-either: + - pattern-inside: | + import javax.crypto.*; + ... + - pattern-inside: | + import javax.crypto.Cipher; + ... + - pattern-either: + - pattern: Cipher.getInstance("AES") + - pattern: (Cipher $CIPHER).getInstance("AES") + metadata: + functional-categories: + - 'crypto::search::mode::javax.crypto' + cwe: + - "CWE-327: Use of a Broken or Risky Cryptographic Algorithm" + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + category: security + technology: + - java + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + - https://googleprojectzero.blogspot.com/2022/10/rc4-is-still-considered-harmful.html + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: HIGH + message: >- + Use of AES with no settings detected. By default, java.crypto.Cipher uses ECB mode. ECB doesn't + provide message confidentiality and is not semantically secure so should not be used. + Instead, use a strong, secure cipher: java.crypto.Cipher.getInstance("AES/CBC/PKCS7PADDING"). + See https://owasp.org/www-community/Using_the_Java_Cryptographic_Extensions + for more information. + severity: WARNING + languages: + - java +- id: java.lang.security.audit.crypto.use-of-md5-digest-utils.use-of-md5-digest-utils + message: >- + Detected MD5 hash algorithm which is considered insecure. MD5 is not + collision resistant and is therefore not suitable as a cryptographic + signature. Use HMAC instead. + languages: [java] + severity: WARNING + metadata: + functional-categories: + - 'crypto::search::hash-algorithm::org.apache.commons' + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + cwe: + - 'CWE-328: Use of Weak Hash' + source-rule-url: https://find-sec-bugs.github.io/bugs.htm#WEAK_MESSAGE_DIGEST_MD5 + category: security + technology: + - java + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: HIGH + patterns: + - pattern: | + $DU.$GET_ALGO().digest(...) + - metavariable-pattern: + metavariable: $GET_ALGO + pattern: getMd5Digest + - metavariable-pattern: + metavariable: $DU + pattern: DigestUtils + - focus-metavariable: $GET_ALGO + fix: | + getSha512Digest + +- id: java.lang.security.audit.crypto.use-of-md5.use-of-md5 + message: >- + Detected MD5 hash algorithm which is considered insecure. MD5 is not + collision resistant and is therefore not suitable as a cryptographic + signature. Use HMAC instead. + languages: [java] + severity: WARNING + metadata: + functional-categories: + - 'crypto::search::hash-algorithm::java.security' + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + cwe: + - 'CWE-328: Use of Weak Hash' + source-rule-url: https://find-sec-bugs.github.io/bugs.htm#WEAK_MESSAGE_DIGEST_MD5 + category: security + technology: + - java + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: HIGH + patterns: + - pattern: | + java.security.MessageDigest.getInstance($ALGO, ...); + - metavariable-regex: + metavariable: "$ALGO" + regex: (.MD5.) + - focus-metavariable: $ALGO + fix: | + "SHA-512" +- id: java.lang.security.audit.crypto.use-of-rc2.use-of-rc2 + pattern: $CIPHER.getInstance("RC2") + metadata: + functional-categories: + - 'crypto::search::symmetric-algorithm::javax.crypto' + cwe: + - 'CWE-327: Use of a Broken or Risky Cryptographic Algorithm' + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + category: security + technology: + - java + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + - https://googleprojectzero.blogspot.com/2022/10/rc4-is-still-considered-harmful.html + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: HIGH + message: >- + Use of RC2 was detected. RC2 is vulnerable to related-key attacks, + and is therefore considered non-compliant. Instead, use a strong, + secure cipher: Cipher.getInstance("AES/CBC/PKCS7PADDING"). + See https://owasp.org/www-community/Using_the_Java_Cryptographic_Extensions + for more information. + severity: WARNING + languages: + - java +- id: java.lang.security.audit.crypto.use-of-rc4.use-of-rc4 + pattern: $CIPHER.getInstance("RC4") + metadata: + functional-categories: + - 'crypto::search::symmetric-algorithm::javax.crypto' + cwe: + - 'CWE-327: Use of a Broken or Risky Cryptographic Algorithm' + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + category: security + technology: + - java + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + - https://googleprojectzero.blogspot.com/2022/10/rc4-is-still-considered-harmful.html + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: HIGH + message: >- + Use of RC4 was detected. RC4 is vulnerable to several attacks, including + stream cipher attacks and bit flipping attacks. Instead, use a strong, + secure cipher: Cipher.getInstance("AES/CBC/PKCS7PADDING"). + See https://owasp.org/www-community/Using_the_Java_Cryptographic_Extensions + for more information. + severity: WARNING + languages: + - java +- id: java.lang.security.audit.crypto.use-of-sha1.use-of-sha1 + message: >- + Detected SHA1 hash algorithm which is considered insecure. SHA1 is not + collision resistant and is therefore not suitable as a cryptographic + signature. Instead, use PBKDF2 for password hashing + or SHA256 or SHA512 for other hash function applications. + languages: [java] + severity: WARNING + metadata: + functional-categories: + - 'crypto::search::hash-algorithm::javax.crypto' + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + cwe: + - 'CWE-328: Use of Weak Hash' + source-rule-url: https://find-sec-bugs.github.io/bugs.htm#WEAK_MESSAGE_DIGEST_SHA1 + asvs: + section: V6 Stored Cryptography Verification Requirements + control_id: 6.2.5 Insecure Algorithm + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x14-V6-Cryptography.md#v62-algorithms + version: '4' + category: security + technology: + - java + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: HIGH + pattern-either: + - patterns: + - pattern: | + java.security.MessageDigest.getInstance("$ALGO", ...); + - metavariable-regex: + metavariable: $ALGO + regex: (SHA1|SHA-1) + - pattern: | + $DU.getSha1Digest().digest(...) +- id: java.lang.security.audit.crypto.weak-random.weak-random + message: >- + Detected use of the functions `Math.random()` or `java.util.Random()`. These are both not + cryptographically strong random number generators (RNGs). If you are using these + RNGs to create passwords or secret tokens, use `java.security.SecureRandom` instead. + languages: [java] + severity: WARNING + metadata: + functional-categories: + - 'crypto::search::randomness::java.security' + owasp: + - A02:2021 - Cryptographic Failures + cwe: + - 'CWE-330: Use of Insufficiently Random Values' + category: security + technology: + - java + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + pattern-either: + - pattern: | + new java.util.Random(...).$FUNC(...) + - pattern: | + java.lang.Math.random(...) +- id: java.lang.security.audit.crypto.weak-rsa.use-of-weak-rsa-key + message: RSA keys should be at least 2048 bits based on NIST recommendation. + languages: [java] + severity: WARNING + metadata: + functional-categories: + - 'crypto::search::key-length::java.security' + cwe: + - 'CWE-326: Inadequate Encryption Strength' + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + source-rule-url: https://find-sec-bugs.github.io/bugs.htm#RSA_KEY_SIZE + asvs: + section: V6 Stored Cryptography Verification Requirements + control_id: 6.2.5 Insecure Algorithm + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x14-V6-Cryptography.md#v62-algorithms + version: '4' + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Cryptographic_Storage_Cheat_Sheet.html#algorithms + category: security + technology: + - java + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: HIGH + patterns: + - pattern: | + KeyPairGenerator $KEY = $G.getInstance("RSA"); + ... + $KEY.initialize($BITS); + - metavariable-comparison: + metavariable: $BITS + comparison: $BITS < 2048 +- id: java.lang.security.audit.dangerous-groovy-shell.dangerous-groovy-shell + patterns: + - pattern-either: + - pattern: | + $SHELL.parse(...) + - pattern: | + $SHELL.evaluate(...) + - pattern: | + $SHELL.parseClass(...) + - pattern-either: + - pattern-inside: | + groovy.lang.GroovyShell $SHELL = ...; + ... + - pattern-inside: | + groovy.lang.GroovyClassLoader $SHELL = ...; + ... + - pattern-not: | + $SHELL.parse("...",...) + - pattern-not: | + $SHELL.evaluate("...",...) + - pattern-not: | + $SHELL.parseClass("...",...) + message: >- + A expression is built with a dynamic value. The source of the value(s) should + be verified to avoid that unfiltered values fall into this risky code evaluation. + metadata: + cwe: + - "CWE-94: Improper Control of Generation of Code ('Code Injection')" + owasp: + - A03:2021 - Injection + source-rule-url: https://find-sec-bugs.github.io/bugs.htm#GROOVY_SHELL + category: security + technology: + - groovy + references: + - https://owasp.org/Top10/A03_2021-Injection + cwe2022-top25: true + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [java] + severity: WARNING +- id: java.lang.security.audit.el-injection.el-injection + metadata: + cwe: + - "CWE-94: Improper Control of Generation of Code ('Code Injection')" + owasp: + - A03:2021 - Injection + source-rule-url: https://find-sec-bugs.github.io/bugs.htm#EL_INJECTION + category: security + technology: + - java + references: + - https://owasp.org/Top10/A03_2021-Injection + cwe2022-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH + confidence: LOW + message: >- + An expression is built with a dynamic value. The source of the value(s) should + be verified to avoid that unfiltered values fall into this risky code evaluation. + severity: WARNING + languages: [java] + patterns: + - pattern-either: + - pattern: | + class $CLASS { + ... + ExpressionFactory $EF; + ... + $X $METHOD(...) { + ... + $EF.createValueExpression($CTX,$INPUT,...); + ... + } + ... + } + - pattern: | + class $CLASS { + ... + ExpressionFactory $EF = ...; + ... + $X $METHOD(...) { + ... + $EF.createValueExpression($CTX,$INPUT,...); + ... + } + ... + } + - pattern: | + $X $METHOD(...) { + ... + ExpressionFactory $EF = ...; + ... + $EF.createValueExpression($CTX,$INPUT,...); + ... + } + - pattern: | + $X $METHOD(...,ExpressionFactory $EF,...) { + ... + $EF.createValueExpression($CTX,$INPUT,...); + ... + } + - pattern: | + class $CLASS { + ... + ExpressionFactory $EF; + ... + $X $METHOD(...) { + ... + $EF.createMethodExpression($CTX,$INPUT,...); + ... + } + ... + } + - pattern: | + class $CLASS { + ... + ExpressionFactory $EF = ...; + ... + $X $METHOD(...) { + ... + $EF.createMethodExpression($CTX,$INPUT,...); + ... + } + ... + } + - pattern: | + $X $METHOD(...) { + ... + ExpressionFactory $EF = ...; + ... + $EF.createMethodExpression($CTX,$INPUT,...); + ... + } + - pattern: | + $X $METHOD(...,ExpressionFactory $EF,...) { + ... + $EF.createMethodExpression($CTX,$INPUT,...); + ... + } + - pattern: | + $X $METHOD(String $INPUT, ...) { + ... + $OBJECT.buildConstraintViolationWithTemplate($INPUT, ...); + ... + } + - pattern-not: | + $X $METHOD(...) { + ... + $EF.createValueExpression($CTX,"...",...); + ... + } + - pattern-not: | + $X $METHOD(...) { + ... + String $S = "..."; + ... + $EF.createValueExpression($CTX,$S,...); + ... + } + - pattern-not: | + $X $METHOD(...) { + ... + $EF.createMethodExpression($CTX,"...",...); + ... + } + - pattern-not: | + $X $METHOD(...) { + ... + String $S = "..."; + ... + $EF.createMethodExpression($CTX,$S,...); + ... + } +- id: java.lang.security.audit.formatted-sql-string.formatted-sql-string + metadata: + cwe: + - "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')" + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + source-rule-url: https://find-sec-bugs.github.io/bugs.htm#SQL_INJECTION + asvs: + section: 'V5: Validation, Sanitization and Encoding Verification Requirements' + control_id: 5.3.5 Injection + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x13-V5-Validation-Sanitization-Encoding.md#v53-output-encoding-and-injection-prevention-requirements + version: '4' + references: + - https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html + - https://docs.oracle.com/javase/tutorial/jdbc/basics/prepared.html#create_ps + - https://software-security.sans.org/developer-how-to/fix-sql-injection-in-java-using-prepared-callable-statement + category: security + technology: + - java + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: HIGH + impact: MEDIUM + confidence: MEDIUM + options: + taint_assume_safe_numbers: true + taint_assume_safe_booleans: true + message: >- + Detected a formatted string in a SQL statement. This could lead to SQL + injection if variables in the SQL statement are not properly sanitized. + Use a prepared statements (java.sql.PreparedStatement) instead. You + can obtain a PreparedStatement using 'connection.prepareStatement'. + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - pattern: | + (HttpServletRequest $REQ) + - patterns: + - pattern-inside: | + $ANNOT $FUNC (..., $INPUT, ...) { + ... + } + - pattern: (String $INPUT) + - focus-metavariable: $INPUT + label: INPUT + - patterns: + - pattern-either: + - pattern: $X + $INPUT + - pattern: $X += $INPUT + - pattern: $STRB.append($INPUT) + - pattern: String.format(..., $INPUT, ...) + - pattern: String.join(..., $INPUT, ...) + - pattern: (String $STR).concat($INPUT) + - pattern: $INPUT.concat(...) + - pattern: new $STRB(..., $INPUT, ...) + label: CONCAT + requires: INPUT + pattern-propagators: + - pattern: (StringBuffer $S).append($X) + from: $X + to: $S + - pattern: (StringBuilder $S).append($X) + from: $X + to: $S + pattern-sinks: + - patterns: + - pattern-not: $S.$SQLFUNC(<... "=~/.*TABLE *$/" ...>) + - pattern-not: $S.$SQLFUNC(<... "=~/.*TABLE %s$/" ...>) + - pattern-either: + - pattern: (Statement $S).$SQLFUNC(...) + - pattern: (PreparedStatement $P).$SQLFUNC(...) + - pattern: (Connection $C).createStatement(...).$SQLFUNC(...) + - pattern: (Connection $C).prepareStatement(...).$SQLFUNC(...) + - pattern: (EntityManager $EM).$SQLFUNC(...) + - metavariable-regex: + metavariable: $SQLFUNC + regex: execute|executeQuery|createQuery|query|addBatch|nativeSQL|create|prepare + requires: CONCAT + pattern-sanitizers: + - patterns: + - pattern: (CriteriaBuilder $CB).$ANY(...) + severity: ERROR + languages: + - java +- id: java.lang.security.audit.http-response-splitting.http-response-splitting + metadata: + cwe: + - "CWE-113: Improper Neutralization of CRLF Sequences in HTTP Headers ('HTTP Request/Response Splitting')" + owasp: + - A03:2021 - Injection + source-rule-url: https://find-sec-bugs.github.io/bugs.htm#HTTP_RESPONSE_SPLITTING + references: + - https://www.owasp.org/index.php/HTTP_Response_Splitting + category: security + technology: + - java + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + message: >- + Older Java application servers are vulnerable to HTTP response splitting, which + may occur if an HTTP + request can be injected with CRLF characters. This finding is reported for completeness; + it is recommended + to ensure your environment is not affected by testing this yourself. + severity: INFO + languages: + - java + pattern-either: + - pattern: | + $VAR = $REQ.getParameter(...); + ... + $COOKIE = new Cookie(..., $VAR, ...); + ... + $RESP.addCookie($COOKIE, ...); + - patterns: + - pattern-inside: | + $RETTYPE $FUNC(...,@PathVariable $TYPE $VAR, ...) { + ... + } + - pattern: | + $COOKIE = new Cookie(..., $VAR, ...); + ... + $RESP.addCookie($COOKIE, ...); +- id: java.lang.security.audit.insecure-smtp-connection.insecure-smtp-connection + metadata: + cwe: + - 'CWE-297: Improper Validation of Certificate with Host Mismatch' + owasp: + - A07:2021 - Identification and Authentication Failures + source-rule-url: https://find-sec-bugs.github.io/bugs.htm#INSECURE_SMTP_SSL + category: security + technology: + - java + references: + - https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures + subcategory: + - vuln + likelihood: LOW + impact: MEDIUM + confidence: MEDIUM + message: >- + Insecure SMTP connection detected. This connection will trust any SSL certificate. + Enable certificate verification by setting 'email.setSSLCheckServerIdentity(true)'. + severity: WARNING + patterns: + - pattern-not-inside: | + $EMAIL.setSSLCheckServerIdentity(true); + ... + - pattern-inside: | + $EMAIL = new SimpleEmail(...); + ... + - pattern: |- + $EMAIL.send(...); + languages: + - java +- id: java.lang.security.audit.java-reverse-shell.java-reverse-shell + patterns: + - pattern-either: + - pattern: | + Socket $S=new Socket(...); + ... + InputStream $SI = $S.getInputStream(); + ... + while(!$S.isClosed()) + { + ... + while($SI.available()>0)$PO.write($SI.read()); + ... + $SO.flush(); + ... + } + - pattern-inside: | + Process $P=new ProcessBuilder(...).redirectErrorStream(true).start(); + ... + $P.destroy(); + message: Semgrep found potential reverse shell behavior + severity: WARNING + metadata: + cwe: + - "CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')" + category: security + technology: [java] + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + references: + - https://owasp.org/Top10/A03_2021-Injection + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH + confidence: LOW + languages: + - java +- id: java.lang.security.audit.jdbc-sql-formatted-string.jdbc-sql-formatted-string + metadata: + cwe: + - "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')" + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + source-rule-url: https://find-sec-bugs.github.io/bugs.htm#SQL_INJECTION_SPRING_JDBC + asvs: + section: 'V5: Validation, Sanitization and Encoding Verification Requirements' + control_id: 5.3.5 Injection + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x13-V5-Validation-Sanitization-Encoding.md#v53-output-encoding-and-injection-prevention-requirements + version: '4' + category: security + technology: + - jdbc + references: + - https://owasp.org/Top10/A03_2021-Injection + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH + confidence: LOW + message: >- + Possible JDBC injection detected. Use the parameterized query + feature available in queryForObject instead of concatenating or formatting strings: + 'jdbc.queryForObject("select * from table where name = ?", Integer.class, parameterName);' + patterns: + - pattern-inside: | + $JDBC = new JdbcTemplate(...); + ... + - pattern-either: + # Unsafe queryForObject + - pattern: $JDBC.queryForObject($STR + $VAR, ...); + - pattern: $JDBC.queryForObject(String.format(...), ...); + - pattern: | + String $Q = $STR + $VAR; + ... + $JDBC.queryForObject($Q, ...); + - pattern: | + String $Q = String.format(...); + ... + $JDBC.queryForObject($Q, ...); + - pattern: | + StringBuilder $Q = new StringBuilder(...); + ... + $Q.append($STR + $VAR); + ... + $JDBC.queryForObject($Q, ...); + - pattern: $JDBC.queryForList($STR + $VAR); + - pattern: $JDBC.queryForList(String.format(...)); + - pattern: | + String $Q = $STR + $VAR; + ... + $JDBC.queryForList($Q); + - pattern: | + String $Q = String.format(...); + ... + $JDBC.queryForList($Q); + - pattern: | + StringBuilder $Q = new StringBuilder(...); + ... + $Q.append($STR + $VAR); + ... + $JDBC.queryForList($Q, ...); + - pattern: $JDBC.update($STR + $VAR); + - pattern: $JDBC.update(String.format(...)); + - pattern: | + String $Q = $STR + $VAR; + ... + $JDBC.update($Q); + - pattern: | + String $Q = String.format(...); + ... + $JDBC.update($Q); + - pattern: | + StringBuilder $Q = new StringBuilder(...); + ... + $Q.append($STR + $VAR); + ... + $JDBC.update($Q, ...); + - pattern: $JDBC.execute($STR + $VAR); + - pattern: $JDBC.execute(String.format(...)); + - pattern: | + String $Q = $STR + $VAR; + ... + $JDBC.execute($Q); + - pattern: | + String $Q = String.format(...); + ... + $JDBC.execute($Q); + - pattern: | + StringBuilder $Q = new StringBuilder(...); + ... + $Q.append($STR + $VAR); + ... + $JDBC.execute($Q, ...); + - pattern: $JDBC.insert($STR + $VAR); + - pattern: $JDBC.insert(String.format(...)); + - pattern: | + String $Q = $STR + $VAR; + ... + $JDBC.insert($Q); + - pattern: | + String $Q = String.format(...); + ... + $JDBC.insert($Q); + - pattern: | + StringBuilder $Q = new StringBuilder(...); + ... + $Q.append($STR + $VAR); + ... + $JDBC.insert($Q, ...); + severity: WARNING + languages: + - java +- id: java.lang.security.audit.ldap-entry-poisoning.ldap-entry-poisoning + metadata: + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + cwe: + - "CWE-90: Improper Neutralization of Special Elements used in an LDAP Query ('LDAP Injection')" + source-rule-url: https://find-sec-bugs.github.io/bugs.htm#LDAP_ENTRY_POISONING + asvs: + section: 'V5: Validation, Sanitization and Encoding Verification Requirements' + control_id: 5.3.7 Injection + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x13-V5-Validation-Sanitization-Encoding.md#v53-output-encoding-and-injection-prevention-requirements + version: '4' + references: + - https://www.blackhat.com/docs/us-16/materials/us-16-Munoz-A-Journey-From-JNDI-LDAP-Manipulation-To-RCE-wp.pdf + - https://cheatsheetseries.owasp.org/cheatsheets/LDAP_Injection_Prevention_Cheat_Sheet.html + category: security + technology: + - java + subcategory: + - audit + likelihood: LOW + impact: HIGH + confidence: LOW + message: >- + An object-returning LDAP search will allow attackers to control the LDAP response. + This could + lead to Remote Code Execution. + severity: WARNING + pattern-either: + # SearchControls(int scope, long countlim, int timelim, String[] attrs, boolean retobj, boolean deref) + - pattern: | + new SearchControls($S, $CL, $TL, $AT, true, $DEREF) + - pattern: | + SearchControls $VAR = new SearchControls(); + ... + $VAR.setReturningObjFlag(true); + languages: + - java +- id: java.lang.security.audit.ldap-injection.ldap-injection + message: >- + Detected non-constant data passed into an LDAP query. If this data can be + controlled by an external user, this is an LDAP injection. + Ensure data passed to an LDAP query is not controllable; or properly sanitize + the data. + metadata: + cwe: + - "CWE-90: Improper Neutralization of Special Elements used in an LDAP Query ('LDAP Injection')" + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + source-rule-url: https://find-sec-bugs.github.io/bugs.htm#LDAP_INJECTION + asvs: + section: 'V5: Validation, Sanitization and Encoding Verification Requirements' + control_id: 5.3.7 Injection + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x13-V5-Validation-Sanitization-Encoding.md#v53-output-encoding-and-injection-prevention-requirements + version: '4' + category: security + technology: + - java + references: + - https://owasp.org/Top10/A03_2021-Injection + subcategory: + - audit + likelihood: LOW + impact: HIGH + confidence: LOW + severity: WARNING + languages: [java] + patterns: + - pattern-either: + - pattern-inside: | + $X $METHOD(...) { + ... + InitialDirContext $CTX = ...; + ... + } + - pattern-inside: | + $X $METHOD(...) { + ... + DirContext $CTX = ...; + ... + } + - pattern-inside: | + $X $METHOD(...) { + ... + InitialLdapContext $CTX = ...; + ... + } + - pattern-inside: | + $X $METHOD(...) { + ... + LdapContext $CTX = ...; + ... + } + - pattern-inside: | + $X $METHOD(...) { + ... + LdapCtx $CTX = ...; + ... + } + - pattern-inside: | + $X $METHOD(...) { + ... + EventDirContext $CTX = ...; + ... + } + - pattern: | + $X $METHOD(...) { + ... + $CTX.search($Y,$INPUT,...); + ... + } + - pattern-not: | + $X $METHOD(...) { + ... + $CTX.search($Y,"...",...); + ... + } +- id: java.lang.security.audit.md5-used-as-password.md5-used-as-password + languages: [java] + severity: WARNING + message: >- + It looks like MD5 is used as a password hash. MD5 is not considered a + secure password hash because it can be cracked by an attacker in a short + amount of time. Use a suitable password hashing function such as PBKDF2 or bcrypt. + You can use `javax.crypto.SecretKeyFactory` with `SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1")` + or, if using Spring, `org.springframework.security.crypto.bcrypt`. + metadata: + category: security + technology: + - java + - md5 + references: + - https://tools.ietf.org/id/draft-lvelvindron-tls-md5-sha1-deprecate-01.html + - https://github.com/returntocorp/semgrep-rules/issues/1609 + - https://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html#SecretKeyFactory + - https://docs.spring.io/spring-security/site/docs/current/api/org/springframework/security/crypto/bcrypt/BCryptPasswordEncoder.html + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + cwe: + - 'CWE-327: Use of a Broken or Risky Cryptographic Algorithm' + subcategory: + - vuln + likelihood: HIGH + impact: MEDIUM + confidence: MEDIUM + mode: taint + pattern-sources: + - patterns: + - pattern-inside: | + $TYPE $MD = MessageDigest.getInstance("MD5"); + ... + - pattern: $MD.digest(...); + pattern-sinks: + - patterns: + - pattern: $MODEL.$METHOD(...); + - metavariable-regex: + metavariable: $METHOD + regex: (?i)(.*password.*) +- id: java.lang.security.audit.object-deserialization.object-deserialization + metadata: + cwe: + - 'CWE-502: Deserialization of Untrusted Data' + owasp: + - A08:2017 - Insecure Deserialization + - A08:2021 - Software and Data Integrity Failures + source-rule-url: https://find-sec-bugs.github.io/bugs.htm#OBJECT_DESERIALIZATION + references: + - https://www.owasp.org/index.php/Deserialization_of_untrusted_data + - https://www.oracle.com/java/technologies/javase/seccodeguide.html#8 + category: security + technology: + - java + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH + confidence: LOW + message: >- + Found object deserialization using ObjectInputStream. Deserializing entire + Java objects is dangerous because malicious actors can create Java object + streams with unintended consequences. Ensure that the objects being deserialized + are not user-controlled. If this must be done, consider using HMACs to sign + the data stream to make sure it is not tampered with, or consider only + transmitting object fields and populating a new object. + severity: WARNING + languages: + - java + pattern: new ObjectInputStream(...); +- id: java.lang.security.audit.ognl-injection.ognl-injection + message: >- + A expression is built with a dynamic value. The source of the value(s) should + be verified to avoid that unfiltered values fall into this risky code evaluation. + metadata: + cwe: + - "CWE-94: Improper Control of Generation of Code ('Code Injection')" + owasp: + - A03:2021 - Injection + source-rule-url: https://find-sec-bugs.github.io/bugs.htm#OGNL_INJECTION + category: security + technology: + - ognl + references: + - https://owasp.org/Top10/A03_2021-Injection + cwe2022-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + severity: WARNING + languages: [java] + patterns: + - pattern-either: + - pattern: | + $X $METHOD(...,OgnlReflectionProvider $P,...) { + ... + $P.getGetMethod($T, $INPUT,...); + ... + } + - pattern: | + $X $METHOD(...,OgnlReflectionProvider $P,...) { + ... + $P.getSetMethod($T, $INPUT,...); + ... + } + - pattern: | + $X $METHOD(...,OgnlReflectionProvider $P,...) { + ... + $P.getField($T, $INPUT,...); + ... + } + - pattern: | + $X $METHOD(...,OgnlReflectionProvider $P,...) { + ... + $P.setProperties($INPUT,...); + ... + } + - pattern: | + $X $METHOD(...,OgnlReflectionProvider $P,...) { + ... + $P.setProperty($INPUT,...); + ... + } + - pattern: | + $X $METHOD(...,OgnlReflectionProvider $P,...) { + ... + $P.getValue($INPUT,...); + ... + } + - pattern: | + $X $METHOD(...,OgnlReflectionProvider $P,...) { + ... + $P.setValue($INPUT,...); + ... + } + - pattern: | + $X $METHOD(...,ReflectionProvider $P,...) { + ... + $P.getGetMethod($T, $INPUT,...); + ... + } + - pattern: | + $X $METHOD(...,ReflectionProvider $P,...) { + ... + $P.getSetMethod($T, $INPUT,...); + ... + } + - pattern: | + $X $METHOD(...,ReflectionProvider $P,...) { + ... + $P.getField($T, $INPUT,...); + ... + } + - pattern: | + $X $METHOD(...,ReflectionProvider $P,...) { + ... + $P.setProperties($INPUT,...); + ... + } + - pattern: | + $X $METHOD(...,ReflectionProvider $P,...) { + ... + $P.setProperty($INPUT,...); + ... + } + - pattern: | + $X $METHOD(...,ReflectionProvider $P,...) { + ... + $P.getValue($INPUT,...); + ... + } + - pattern: | + $X $METHOD(...,ReflectionProvider $P,...) { + ... + $P.setValue($INPUT,...); + ... + } + - pattern: | + $X $METHOD(...,TextParseUtil $P,...) { + ... + $P.translateVariables($INPUT,...); + ... + } + - pattern: | + $X $METHOD(...,TextParseUtil $P,...) { + ... + $P.translateVariablesCollection($INPUT,...); + ... + } + - pattern: | + $X $METHOD(...,TextParseUtil $P,...) { + ... + $P.shallBeIncluded($INPUT,...); + ... + } + - pattern: | + $X $METHOD(...,TextParseUtil $P,...) { + ... + $P.commaDelimitedStringToSet($INPUT,...); + ... + } + - pattern: | + $X $METHOD(...,TextParser $P,...) { + ... + $P.evaluate($INPUT,...); + ... + } + - pattern: | + $X $METHOD(...,OgnlTextParser $P,...) { + ... + $P.evaluate($INPUT,...); + ... + } + - pattern: | + $X $METHOD(...,OgnlUtil $P,...) { + ... + $P.setProperties($INPUT,...); + ... + } + - pattern: | + $X $METHOD(...,OgnlUtil $P,...) { + ... + $P.setProperty($INPUT,...); + ... + } + - pattern: | + $X $METHOD(...,OgnlUtil $P,...) { + ... + $P.getValue($INPUT,...); + ... + } + - pattern: | + $X $METHOD(...,OgnlUtil $P,...) { + ... + $P.setValue($INPUT,...); + ... + } + - pattern: | + $X $METHOD(...,OgnlUtil $P,...) { + ... + $P.callMethod($INPUT,...); + ... + } + - pattern: | + $X $METHOD(...,OgnlUtil $P,...) { + ... + $P.compile($INPUT,...); + ... + } + - pattern: | + $X $METHOD(...,VelocityStrutsUtil $P,...) { + ... + $P.evaluate($INPUT,...); + ... + } + - pattern: | + $X $METHOD(...,StrutsUtil $P,...) { + ... + $P.isTrue($INPUT,...); + ... + } + - pattern: | + $X $METHOD(...,StrutsUtil $P,...) { + ... + $P.findString($INPUT,...); + ... + } + - pattern: | + $X $METHOD(...,StrutsUtil $P,...) { + ... + $P.findValue($INPUT,...); + ... + } + - pattern: | + $X $METHOD(...,StrutsUtil $P,...) { + ... + $P.getText($INPUT,...); + ... + } + - pattern: | + $X $METHOD(...,StrutsUtil $P,...) { + ... + $P.translateVariables($INPUT,...); + ... + } + - pattern: | + $X $METHOD(...,StrutsUtil $P,...) { + ... + $P.makeSelectList($INPUT,...); + ... + } + - pattern: | + $X $METHOD(...,OgnlTool $P,...) { + ... + $P.findValue($INPUT,...); + ... + } + - pattern: | + $X $METHOD(...,ValueStack $P,...) { + ... + $P.findString($INPUT,...); + ... + } + - pattern: | + $X $METHOD(...,ValueStack $P,...) { + ... + $P.findValue($INPUT,...); + ... + } + - pattern: | + $X $METHOD(...,ValueStack $P,...) { + ... + $P.setValue($INPUT,...); + ... + } + - pattern: | + $X $METHOD(...,ValueStack $P,...) { + ... + $P.setParameter($INPUT,...); + ... + } + - pattern: | + $X $METHOD(...) { + ... + OgnlReflectionProvider $P = ...; + ... + $P.getGetMethod($T, $INPUT,...); + ... + } + - pattern: | + $X $METHOD(...) { + ... + OgnlReflectionProvider $P = ...; + ... + $P.getSetMethod($T, $INPUT,...); + ... + } + - pattern: | + $X $METHOD(...) { + ... + OgnlReflectionProvider $P = ...; + ... + $P.getField($T, $INPUT,...); + ... + } + - pattern: | + $X $METHOD(...) { + ... + OgnlReflectionProvider $P = ...; + ... + $P.setProperties($INPUT,...); + ... + } + - pattern: | + $X $METHOD(...) { + ... + OgnlReflectionProvider $P = ...; + ... + $P.setProperty($INPUT,...); + ... + } + - pattern: | + $X $METHOD(...) { + ... + OgnlReflectionProvider $P = ...; + ... + $P.getValue($INPUT,...); + ... + } + - pattern: | + $X $METHOD(...) { + ... + OgnlReflectionProvider $P = ...; + ... + $P.setValue($INPUT,...); + ... + } + - pattern: | + $X $METHOD(...) { + ... + ReflectionProvider $P = ...; + ... + $P.getGetMethod($T, $INPUT,...); + ... + } + - pattern: | + $X $METHOD(...) { + ... + ReflectionProvider $P = ...; + ... + $P.getSetMethod($T, $INPUT,...); + ... + } + - pattern: | + $X $METHOD(...) { + ... + ReflectionProvider $P = ...; + ... + $P.getField($T, $INPUT,...); + ... + } + - pattern: | + $X $METHOD(...) { + ... + ReflectionProvider $P = ...; + ... + $P.setProperties($INPUT,...); + ... + } + - pattern: | + $X $METHOD(...) { + ... + ReflectionProvider $P = ...; + ... + $P.setProperty($INPUT,...); + ... + } + - pattern: | + $X $METHOD(...) { + ... + ReflectionProvider $P = ...; + ... + $P.getValue($INPUT,...); + ... + } + - pattern: | + $X $METHOD(...) { + ... + ReflectionProvider $P = ...; + ... + $P.setValue($INPUT,...); + ... + } + - pattern: | + $X $METHOD(...) { + ... + TextParseUtil $P = ...; + ... + $P.translateVariables($INPUT,...); + ... + } + - pattern: | + $X $METHOD(...) { + ... + TextParseUtil $P = ...; + ... + $P.translateVariablesCollection($INPUT,...); + ... + } + - pattern: | + $X $METHOD(...) { + ... + TextParseUtil $P = ...; + ... + $P.shallBeIncluded($INPUT,...); + ... + } + - pattern: | + $X $METHOD(...) { + ... + TextParseUtil $P = ...; + ... + $P.commaDelimitedStringToSet($INPUT,...); + ... + } + - pattern: | + $X $METHOD(...) { + ... + TextParser $P = ...; + ... + $P.evaluate($INPUT,...); + ... + } + - pattern: | + $X $METHOD(...) { + ... + OgnlTextParser $P = ...; + ... + $P.evaluate($INPUT,...); + ... + } + - pattern: | + $X $METHOD(...) { + ... + OgnlUtil $P = ...; + ... + $P.setProperties($INPUT,...); + ... + } + - pattern: | + $X $METHOD(...) { + ... + OgnlUtil $P = ...; + ... + $P.setProperty($INPUT,...); + ... + } + - pattern: | + $X $METHOD(...) { + ... + OgnlUtil $P = ...; + ... + $P.getValue($INPUT,...); + ... + } + - pattern: | + $X $METHOD(...) { + ... + OgnlUtil $P = ...; + ... + $P.setValue($INPUT,...); + ... + } + - pattern: | + $X $METHOD(...) { + ... + OgnlUtil $P = ...; + ... + $P.callMethod($INPUT,...); + ... + } + - pattern: | + $X $METHOD(...) { + ... + OgnlUtil $P = ...; + ... + $P.compile($INPUT,...); + ... + } + - pattern: | + $X $METHOD(...) { + ... + VelocityStrutsUtil $P = ...; + ... + $P.evaluate($INPUT,...); + ... + } + - pattern: | + $X $METHOD(...) { + ... + StrutsUtil $P = ...; + ... + $P.isTrue($INPUT,...); + ... + } + - pattern: | + $X $METHOD(...) { + ... + StrutsUtil $P = ...; + ... + $P.findString($INPUT,...); + ... + } + - pattern: | + $X $METHOD(...) { + ... + StrutsUtil $P = ...; + ... + $P.findValue($INPUT,...); + ... + } + - pattern: | + $X $METHOD(...) { + ... + StrutsUtil $P = ...; + ... + $P.getText($INPUT,...); + ... + } + - pattern: | + $X $METHOD(...) { + ... + StrutsUtil $P = ...; + ... + $P.translateVariables($INPUT,...); + ... + } + - pattern: | + $X $METHOD(...) { + ... + StrutsUtil $P = ...; + ... + $P.makeSelectList($INPUT,...); + ... + } + - pattern: | + $X $METHOD(...) { + ... + OgnlTool $P = ...; + ... + $P.findValue($INPUT,...); + ... + } + - pattern: | + $X $METHOD(...) { + ... + ValueStack $P = ...; + ... + $P.findString($INPUT,...); + ... + } + - pattern: | + $X $METHOD(...) { + ... + ValueStack $P = ...; + ... + $P.findValue($INPUT,...); + ... + } + - pattern: | + $X $METHOD(...) { + ... + ValueStack $P = ...; + ... + $P.setValue($INPUT,...); + ... + } + - pattern: | + $X $METHOD(...) { + ... + ValueStack $P = ...; + ... + $P.setParameter($INPUT,...); + ... + } + - pattern-not: | + $X $METHOD(...) { + ... + $P.getGetMethod($T,"...",...); + ... + } + - pattern-not: | + $X $METHOD(...) { + ... + $P.getSetMethod($T,"...",...); + ... + } + - pattern-not: | + $X $METHOD(...) { + ... + $P.getField($T,"...",...); + ... + } + - pattern-not: | + $X $METHOD(...) { + ... + $P.setProperties("...",...); + ... + } + - pattern-not: | + $X $METHOD(...) { + ... + $P.setProperty("...",...); + ... + } + - pattern-not: | + $X $METHOD(...) { + ... + $P.getValue("...",...); + ... + } + - pattern-not: | + $X $METHOD(...) { + ... + $P.setValue("...",...); + ... + } + - pattern-not: | + $X $METHOD(...) { + ... + $P.translateVariables("...",...); + ... + } + - pattern-not: | + $X $METHOD(...) { + ... + $P.translateVariablesCollection("...",...); + ... + } + - pattern-not: | + $X $METHOD(...) { + ... + $P.shallBeIncluded("...",...); + ... + } + - pattern-not: | + $X $METHOD(...) { + ... + $P.commaDelimitedStringToSet("...",...); + ... + } + - pattern-not: | + $X $METHOD(...) { + ... + $P.evaluate("...",...); + ... + } + - pattern-not: | + $X $METHOD(...) { + ... + $P.callMethod("...",...); + ... + } + - pattern-not: | + $X $METHOD(...) { + ... + $P.compile("...",...); + ... + } + - pattern-not: | + $X $METHOD(...) { + ... + $P.isTrue("...",...); + ... + } + - pattern-not: | + $X $METHOD(...) { + ... + $P.findString("...",...); + ... + } + - pattern-not: | + $X $METHOD(...) { + ... + $P.findValue("...",...); + ... + } + - pattern-not: | + $X $METHOD(...) { + ... + $P.getText("...",...); + ... + } + - pattern-not: | + $X $METHOD(...) { + ... + $P.makeSelectList("...",...); + ... + } + - pattern-not: | + $X $METHOD(...) { + ... + $P.setParameter("...",...); + ... + } + - pattern-not: | + $X $METHOD(...) { + ... + String $S = "..."; + ... + $P.getGetMethod($T,$S,...); + ... + } + - pattern-not: | + $X $METHOD(...) { + ... + String $S = "..."; + ... + $P.getSetMethod($T,$S,...); + ... + } + - pattern-not: | + $X $METHOD(...) { + ... + String $S = "..."; + ... + $P.getField($T,$S,...); + ... + } + - pattern-not: | + $X $METHOD(...) { + ... + String $S = "..."; + ... + $P.setProperties($S,...); + ... + } + - pattern-not: | + $X $METHOD(...) { + ... + String $S = "..."; + ... + $P.setProperty($S,...); + ... + } + - pattern-not: | + $X $METHOD(...) { + ... + String $S = "..."; + ... + $P.getValue($S,...); + ... + } + - pattern-not: | + $X $METHOD(...) { + ... + String $S = "..."; + ... + $P.setValue($S,...); + ... + } + - pattern-not: | + $X $METHOD(...) { + ... + String $S = "..."; + ... + $P.translateVariables($S,...); + ... + } + - pattern-not: | + $X $METHOD(...) { + ... + String $S = "..."; + ... + $P.translateVariablesCollection($S,...); + ... + } + - pattern-not: | + $X $METHOD(...) { + ... + String $S = "..."; + ... + $P.shallBeIncluded($S,...); + ... + } + - pattern-not: | + $X $METHOD(...) { + ... + String $S = "..."; + ... + $P.commaDelimitedStringToSet($S,...); + ... + } + - pattern-not: | + $X $METHOD(...) { + ... + String $S = "..."; + ... + $P.evaluate($S,...); + ... + } + - pattern-not: | + $X $METHOD(...) { + ... + String $S = "..."; + ... + $P.callMethod($S,...); + ... + } + - pattern-not: | + $X $METHOD(...) { + ... + String $S = "..."; + ... + $P.compile($S,...); + ... + } + - pattern-not: | + $X $METHOD(...) { + ... + String $S = "..."; + ... + $P.isTrue($S,...); + ... + } + - pattern-not: | + $X $METHOD(...) { + ... + String $S = "..."; + ... + $P.findString($S,...); + ... + } + - pattern-not: | + $X $METHOD(...) { + ... + String $S = "..."; + ... + $P.findValue($S,...); + ... + } + - pattern-not: | + $X $METHOD(...) { + ... + String $S = "..."; + ... + $P.getText($S,...); + ... + } + - pattern-not: | + $X $METHOD(...) { + ... + String $S = "..."; + ... + $P.makeSelectList($S,...); + ... + } + - pattern-not: | + $X $METHOD(...) { + ... + String $S = "..."; + ... + $P.setParameter($S,...); + ... + } +- id: java.lang.security.audit.overly-permissive-file-permission.overly-permissive-file-permission + message: >- + Detected file permissions that are overly permissive (read, write, and execute). + It is generally a bad practices to set overly permissive file permission such + as read+write+exec for all users. + If the file affected is a configuration, a binary, a script or sensitive data, + it can lead to privilege escalation or information leakage. + Instead, follow the principle of least privilege and give users only the + permissions they need. + severity: WARNING + languages: [java] + metadata: + cwe: + - 'CWE-276: Incorrect Default Permissions' + owasp: + - A01:2021 - Broken Access Control + source-rule-url: https://find-sec-bugs.github.io/bugs.htm#OVERLY_PERMISSIVE_FILE_PERMISSION + category: security + technology: + - java + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + pattern-either: + - pattern: java.nio.file.Files.setPosixFilePermissions($FILE, java.nio.file.attribute.PosixFilePermissions.fromString("=~/(^......r..$)|(^.......w.$)|(^........x$)/")); + - pattern: | + $TYPE $P = java.nio.file.attribute.PosixFilePermissions.fromString("=~/(^......r..$)|(^.......w.$)|(^........x$)/"); + ... + java.nio.file.Files.setPosixFilePermissions($FILE, $P); + - pattern: | + $P.add(java.nio.file.attribute.PosixFilePermission.OTHERS_READ); + ... + java.nio.file.Files.setPosixFilePermissions($FILE, $P); + - pattern: | + $P.add(java.nio.file.attribute.PosixFilePermission.OTHERS_WRITE); + ... + java.nio.file.Files.setPosixFilePermissions($FILE, $P); + - pattern: |- + $P.add(java.nio.file.attribute.PosixFilePermission.OTHERS_EXECUTE); + ... + java.nio.file.Files.setPosixFilePermissions($FILE, $P); +- id: java.lang.security.audit.permissive-cors.permissive-cors + message: >- + https://find-sec-bugs.github.io/bugs.htm#PERMISSIVE_CORS + Permissive CORS policy will allow a malicious application to communicate with + the victim application in an inappropriate way, leading to spoofing, data theft, + relay and other attacks. + metadata: + cwe: + - 'CWE-183: Permissive List of Allowed Inputs' + asvs: + section: 'V14: Configuration Verification Requirements' + control_id: 14.4.8 Permissive CORS + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x22-V14-Config.md#v144-http-security-headers-requirements + version: '4' + category: security + technology: + - java + owasp: + - A04:2021 - Insecure Design + references: + - https://owasp.org/Top10/A04_2021-Insecure_Design + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + severity: WARNING + languages: [java] + pattern-either: + - pattern: | + HttpServletResponse $RES = ...; + ... + $RES.addHeader("=~/access-control-allow-origin/i", "=~/^\*|null$/i"); + - pattern: | + HttpServletResponse $RES = ...; + ... + $RES.setHeader("=~/access-control-allow-origin/i", "=~/^\*|null$/i"); + - pattern: | + ServerHttpResponse $RES = ...; + ... + $RES.getHeaders().add("=~/access-control-allow-origin/i", "=~/^\*|null$/i"); + - pattern: | + HttpHeaders $HEADERS = ...; + ... + $HEADERS.set("=~/access-control-allow-origin/i", "=~/^\*|null$/i"); + - pattern: | + ServerWebExchange $SWE = ...; + ... + $SWE.getResponse().getHeaders().add("Access-Control-Allow-Origin", "*"); + - pattern: | + $X $METHOD(...,HttpServletResponse $RES,...) { + ... + $RES.addHeader("=~/access-control-allow-origin/i", "=~/^\*|null$/i"); + ... + } + - pattern: | + $X $METHOD(...,HttpServletResponse $RES,...) { + ... + $RES.setHeader("=~/access-control-allow-origin/i", "=~/^\*|null$/i"); + ... + } + - pattern: | + $X $METHOD(...,ServerHttpResponse $RES,...) { + ... + $RES.getHeaders().add("=~/access-control-allow-origin/i", "=~/^\*|null$/i"); + ... + } + - pattern: | + $X $METHOD(...,ServerWebExchange $SWE,...) { + ... + $SWE.getResponse().getHeaders().add("=~/access-control-allow-origin/i", "=~/^\*|null$/i"); + ... + } + - pattern: ResponseEntity.$RES().header("=~/access-control-allow-origin/i", "=~/^\*|null$/i") + - pattern: ServerResponse.$RES().header("=~/access-control-allow-origin/i", "=~/^\*|null$/i") +- id: java.lang.security.audit.script-engine-injection.script-engine-injection + message: >- + Detected potential code injection using ScriptEngine. Ensure + user-controlled data cannot enter '.eval()', otherwise, this is + a code injection vulnerability. + metadata: + cwe: + - "CWE-94: Improper Control of Generation of Code ('Code Injection')" + owasp: + - A03:2021 - Injection + source-rule-url: https://find-sec-bugs.github.io/bugs.htm#SCRIPT_ENGINE_INJECTION + category: security + technology: + - java + references: + - https://owasp.org/Top10/A03_2021-Injection + cwe2022-top25: true + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + severity: WARNING + languages: [java] + patterns: + - pattern-either: + - pattern-inside: | + class $CLASS { + ... + ScriptEngine $SE; + ... + } + - pattern-inside: | + class $CLASS { + ... + ScriptEngine $SE = ...; + ... + } + - pattern-inside: | + $X $METHOD(...) { + ... + ScriptEngine $SE = ...; + ... + } + - pattern: | + $X $METHOD(...) { + ... + $SE.eval(...); + ... + } + - pattern-not: | + $X $METHOD(...) { + ... + $SE.eval("..."); + ... + } + - pattern-not: | + $X $METHOD(...) { + ... + String $S = "..."; + ... + $SE.eval($S); + ... + } +- id: java.lang.security.audit.sqli.hibernate-sqli.hibernate-sqli + pattern-either: + - patterns: + - pattern-either: + - pattern-inside: | + String $SQL = $X + $Y; + ... + - pattern-inside: | + String $SQL = String.format(...); + ... + - pattern-inside: | + $VAL $FUNC(...,String $SQL,...) { + ... + } + - pattern-not-inside: | + String $SQL = "..." + "..."; + ... + - pattern: org.hibernate.criterion.Restrictions.sqlRestriction($SQL,...) + - pattern: org.hibernate.criterion.Restrictions.sqlRestriction(String.format(...),...) + - patterns: + - pattern: org.hibernate.criterion.Restrictions.sqlRestriction($X + $Y,...) + - pattern-not: org.hibernate.criterion.Restrictions.sqlRestriction("..." + "...",...) + - patterns: + - pattern-either: + - patterns: + - pattern-either: + - pattern-inside: | + String $SQL = $X + $Y; + ... + - pattern-inside: | + String $SQL = String.format(...); + ... + - pattern-inside: | + $TYPE $FUNC(...,String $SQL,...) { + ... + } + - pattern-not-inside: | + String $SQL = "..." + "..."; + ... + - pattern: $SESSION.$METHOD($SQL,...) + - pattern: | + $SESSION.$METHOD(String.format(...),...); + - pattern: | + $SESSION.$METHOD($X + $Y,...); + - pattern-either: + - pattern-inside: | + org.hibernate.Session $SESSION = ...; + ... + - pattern-inside: | + $TYPE $FUNC(...,org.hibernate.Session $SESSION,...) { + ... + } + - pattern-not: | + $SESSION.$METHOD("..." + "...",...); + - metavariable-regex: + metavariable: $METHOD + regex: ^(createQuery|createSQLQuery)$ + message: >- + Detected a formatted string in a SQL statement. This could lead to SQL + injection if variables in the SQL statement are not properly sanitized. + Use a prepared statements (java.sql.PreparedStatement) instead. You + can obtain a PreparedStatement using 'connection.prepareStatement'. + metadata: + cwe: + - "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')" + source-rule-url: https://find-sec-bugs.github.io/bugs.htm#SQL_INJECTION_HIBERNATE + asvs: + section: V5 Stored Cryptography Verification Requirements + control_id: 5.3.5 Insecure Custom Algorithm + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x13-V5-Validation-Sanitization-Encoding.md#v53-output-encoding-and-injection-prevention-requirements + version: '4' + category: security + technology: + - hibernate + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + references: + - https://owasp.org/Top10/A03_2021-Injection + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH + confidence: LOW + languages: [java] + severity: WARNING +- id: java.lang.security.audit.sqli.jdbc-sqli.jdbc-sqli + message: >- + Detected a formatted string in a SQL statement. This could lead to SQL + injection if variables in the SQL statement are not properly sanitized. + Use a prepared statements (java.sql.PreparedStatement) instead. You + can obtain a PreparedStatement using 'connection.prepareStatement'. + languages: [java] + severity: WARNING + patterns: + - pattern-either: + - patterns: + - pattern-either: + - pattern-inside: | + String $SQL = $X + $Y; + ... + - pattern-inside: | + String $SQL = String.format(...); + ... + - pattern-inside: | + $VAL $FUNC(...,String $SQL,...) { + ... + } + - pattern-not-inside: | + String $SQL = "..." + "..."; + ... + - pattern: $S.$METHOD($SQL,...) + - pattern: | + $S.$METHOD(String.format(...),...); + - pattern: | + $S.$METHOD($X + $Y,...); + - pattern-either: + - pattern-inside: | + java.sql.Statement $S = ...; + ... + - pattern-inside: | + $TYPE $FUNC(...,java.sql.Statement $S,...) { + ... + } + - pattern-not: | + $S.$METHOD("..." + "...",...); + - metavariable-regex: + metavariable: $METHOD + regex: ^(executeQuery|execute|executeUpdate|executeLargeUpdate|addBatch|nativeSQL)$ + metadata: + cwe: + - "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')" + category: security + technology: + - jdbc + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + references: + - https://owasp.org/Top10/A03_2021-Injection + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH + confidence: LOW +- id: java.lang.security.audit.sqli.jdo-sqli.jdo-sqli + pattern-either: + - patterns: + - pattern-either: + - patterns: + - pattern-either: + - pattern-inside: | + String $SQL = $X + $Y; + ... + - pattern-inside: | + String $SQL = String.format(...); + ... + - pattern-inside: | + $TYPE $FUNC(...,String $SQL,...) { + ... + } + - pattern-not-inside: | + String $SQL = "..." + "..."; + ... + - pattern: $Q.$METHOD($SQL,...) + - pattern: | + $Q.$METHOD(String.format(...),...); + - pattern: | + $Q.$METHOD($X + $Y,...); + - pattern-either: + - pattern-inside: | + javax.jdo.Query $Q = ...; + ... + - pattern-inside: | + $TYPE $FUNC(...,javax.jdo.Query $Q,...) { + ... + } + - pattern-not: | + $Q.$METHOD("..." + "...",...); + - metavariable-regex: + metavariable: $METHOD + regex: ^(setFilter|setGrouping)$ + - patterns: + - pattern-either: + - patterns: + - pattern-either: + - pattern-inside: | + String $SQL = $X + $Y; + ... + - pattern-inside: | + String $SQL = String.format(...); + ... + - pattern-inside: | + $VAL $FUNC(...,String $SQL,...) { + ... + } + - pattern-not-inside: | + String $SQL = "..." + "..."; + ... + - pattern: $PM.newQuery(...,$SQL,...) + - pattern: | + $PM.newQuery(...,String.format(...),...); + - pattern: | + $PM.newQuery(...,$X + $Y,...); + - pattern-either: + - pattern-inside: | + javax.jdo.PersistenceManager $PM = ...; + ... + - pattern-inside: | + $TYPE $FUNC(...,javax.jdo.PersistenceManager $PM,...) { + ... + } + - pattern-not: | + $PM.newQuery(...,"..." + "...",...); + message: >- + Detected a formatted string in a SQL statement. This could lead to SQL + injection if variables in the SQL statement are not properly sanitized. + Use a prepared statements (java.sql.PreparedStatement) instead. You + can obtain a PreparedStatement using 'connection.prepareStatement'. + languages: [java] + severity: WARNING + metadata: + cwe: + - "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')" + category: security + technology: + - java + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + references: + - https://owasp.org/Top10/A03_2021-Injection + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH + confidence: LOW +- id: java.lang.security.audit.sqli.jpa-sqli.jpa-sqli + message: >- + Detected a formatted string in a SQL statement. This could lead to SQL + injection if variables in the SQL statement are not properly sanitized. + Use a prepared statements (java.sql.PreparedStatement) instead. You + can obtain a PreparedStatement using 'connection.prepareStatement'. + languages: [java] + severity: WARNING + patterns: + - pattern-either: + - patterns: + - pattern-either: + - pattern-inside: | + String $SQL = $X + $Y; + ... + - pattern-inside: | + String $SQL = String.format(...); + ... + - pattern-inside: | + $TYPE $FUNC(...,String $SQL,...) { + ... + } + - pattern-not-inside: | + String $SQL = "..." + "..."; + ... + - pattern: $EM.$METHOD($SQL,...) + - pattern: | + $EM.$METHOD(String.format(...),...); + - pattern: | + $EM.$METHOD($X + $Y,...); + - pattern-either: + - pattern-inside: | + EntityManager $EM = ...; + ... + - pattern-inside: | + $TYPE $FUNC(...,EntityManager $EM,...) { + ... + } + - pattern-not: | + $EM.$METHOD("..." + "...",...); + - metavariable-regex: + metavariable: $METHOD + regex: ^(createQuery|createNativeQuery)$ + metadata: + cwe: + - "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')" + category: security + technology: + - jpa + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + references: + - https://owasp.org/Top10/A03_2021-Injection + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH + confidence: LOW +- id: java.lang.security.audit.sqli.tainted-sql-from-http-request.tainted-sql-from-http-request + message: >- + Detected input from a HTTPServletRequest going into a SQL sink or statement. This + could lead to SQL + injection if variables in the SQL statement are not properly sanitized. + Use parameterized SQL queries or properly sanitize user input instead. + severity: WARNING + metadata: + likelihood: HIGH + impact: MEDIUM + confidence: HIGH + category: security + cwe: + - "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + references: + - https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html + - https://owasp.org/www-community/attacks/SQL_Injection + subcategory: + - vuln + technology: + - sql + - java + - servlets + - spring + languages: [java] + mode: taint + options: + taint_assume_safe_numbers: true + taint_assume_safe_booleans: true + pattern-sources: + - patterns: + - pattern-either: + - pattern: | + (HttpServletRequest $REQ).$REQFUNC(...) + - pattern: | + (ServletRequest $REQ).$REQFUNC(...) + - metavariable-regex: + metavariable: $REQFUNC + regex: (getInputStream|getParameter|getParameterMap|getParameterValues|getReader|getCookies|getHeader|getHeaderNames|getHeaders|getPart|getParts|getQueryString) + pattern-sinks: + - patterns: + - pattern-either: + - pattern: | + (java.sql.CallableStatement $STMT) = ...; + - pattern: | + (java.sql.Statement $STMT) = ...; + ... + $OUTPUT = $STMT.$FUNC(...); + - pattern: | + (java.sql.PreparedStatement $STMT) = ...; + - pattern: | + $VAR = $CONN.prepareStatement(...) + - pattern: | + $PATH.queryForObject(...); + - pattern: | + (java.util.Map $STMT) = $PATH.queryForMap(...); + - pattern: | + (org.springframework.jdbc.support.rowset.SqlRowSet $STMT) = ...; + - pattern: | + (org.springframework.jdbc.core.JdbcTemplate $TEMPL).batchUpdate(...) + - patterns: + - pattern-inside: | + (String $SQL) = "$SQLSTR" + ...; + ... + - pattern: $PATH.$SQLCMD(..., $SQL, ...); + - metavariable-regex: + metavariable: $SQLSTR + regex: (?i)(^SELECT.* | ^INSERT.* | ^UPDATE.*) + - metavariable-regex: + metavariable: $SQLCMD + regex: (execute|query|executeUpdate|batchUpdate) +- id: java.lang.security.audit.sqli.turbine-sqli.turbine-sqli + pattern-either: + - patterns: + - pattern-either: + - patterns: + - pattern-either: + - pattern-inside: | + String $SQL = $X + $Y; + ... + - pattern-inside: | + String $SQL = String.format(...); + ... + - pattern-inside: | + $VAL $FUNC(...,String $SQL,...) { + ... + } + - pattern-not-inside: | + String $SQL = "..." + "..."; + ... + - pattern: $PEER.executeQuery($SQL,...) + - pattern: | + $PEER.executeQuery(String.format(...),...) + - pattern: | + $PEER.executeQuery($X + $Y,...) + - pattern-not: | + $PEER.executeQuery("..." + "...",...) + - metavariable-regex: + metavariable: $PEER + regex: (BasePeer|GroupPeer) + - patterns: + - pattern-either: + - patterns: + - pattern-either: + - pattern-inside: | + String $SQL = $X + $Y; + ... + - pattern-inside: | + String $SQL = String.format(...); + ... + - pattern-inside: | + $VAL $FUNC(...,String $SQL,...) { + ... + } + - pattern-not-inside: | + String $SQL = "..." + "..."; + ... + - pattern: $P.executeQuery($SQL,...) + - pattern: | + $P.executeQuery(String.format(...),...) + - pattern: | + $P.executeQuery($X + $Y,...) + - pattern-either: + - pattern-inside: | + BasePeer $P = ...; + ... + - pattern-inside: | + GroupPeer $P = ...; + ... + - pattern-inside: | + $VAL $FUNC(...,GroupPeer $P,...) { + ... + } + - pattern-inside: | + $VAL $FUNC(...,BasePeer $P,...) { + ... + } + - pattern-not: | + $P.executeQuery("..." + "...",...) + message: >- + Detected a formatted string in a SQL statement. This could lead to SQL + injection if variables in the SQL statement are not properly sanitized. + Use a prepared statements (java.sql.PreparedStatement) instead. You + can obtain a PreparedStatement using 'connection.prepareStatement'. + languages: [java] + severity: WARNING + metadata: + cwe: + - "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')" + category: security + technology: + - turbine + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + references: + - https://owasp.org/Top10/A03_2021-Injection + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH + confidence: LOW +- id: java.lang.security.audit.sqli.vertx-sqli.vertx-sqli + message: >- + Detected a formatted string in a SQL statement. This could lead to SQL + injection if variables in the SQL statement are not properly sanitized. + Use a prepared statements (java.sql.PreparedStatement) instead. You + can obtain a PreparedStatement using 'connection.prepareStatement'. + languages: [java] + severity: WARNING + patterns: + - pattern-either: + - patterns: + - pattern-either: + - pattern-inside: | + String $SQL = $X + $Y; + ... + - pattern-inside: | + String $SQL = String.format(...); + ... + - pattern-inside: | + $TYPE $FUNC(...,String $SQL,...) { + ... + } + - pattern-not-inside: | + String $SQL = "..." + "..."; + ... + - pattern: $SC.$METHOD($SQL,...) + - pattern: | + $SC.$METHOD(String.format(...),...); + - pattern: | + $SC.$METHOD($X + $Y,...); + - pattern-either: + - pattern-inside: | + SqlClient $SC = ...; + ... + - pattern-inside: | + SqlConnection $SC = ...; + ... + - pattern-inside: | + $TYPE $FUNC(...,SqlClient $SC,...) { + ... + } + - pattern-inside: | + $TYPE $FUNC(...,SqlConnection $SC,...) { + ... + } + - pattern-not: | + $SC.$METHOD("..." + "...",...); + - metavariable-regex: + metavariable: $METHOD + regex: ^(query|preparedQuery|prepare)$ + metadata: + cwe: + - "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')" + category: security + technology: + - vertx + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + references: + - https://owasp.org/Top10/A03_2021-Injection + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH + confidence: LOW +- id: java.lang.security.audit.tainted-cmd-from-http-request.tainted-cmd-from-http-request + message: >- + Detected input from a HTTPServletRequest going into a 'ProcessBuilder' or 'exec' command. This could + lead to command injection if variables passed into the exec commands are not properly sanitized. Instead, + avoid using these OS commands with user-supplied input, or, if you must use these commands, use a + whitelist of specific values. + languages: [java] + severity: ERROR + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - pattern: | + (HttpServletRequest $REQ) + - patterns: # this pattern is a hack to get the rule to recognize `map` as tainted source when `cookie.getValue(user_input)` is used. + - pattern-inside: | + (javax.servlet.http.Cookie[] $COOKIES) = (HttpServletRequest $REQ).getCookies(...); + ... + for (javax.servlet.http.Cookie $COOKIE: $COOKIES) { + ... + } + - pattern: | + $COOKIE.getValue(...) + pattern-sinks: + - patterns: + - pattern-either: + - pattern: | + (ProcessBuilder $PB) = ...; + - patterns: + - pattern: | + (Process $P) = ...; + - pattern-not: | + (Process $P) = (java.lang.Runtime $R).exec(...); + - patterns: + - pattern: (java.lang.Runtime $R).exec($CMD, ...); + - focus-metavariable: $CMD + - patterns: + - pattern-either: + - pattern-inside: | + (java.util.List<$TYPE> $ARGLIST) = ...; + ... + (ProcessBuilder $PB) = ...; + ... + $PB.command($ARGLIST); + - pattern-inside: | + (java.util.List<$TYPE> $ARGLIST) = ...; + ... + (ProcessBuilder $PB) = ...; + - pattern-inside: | + (java.util.List<$TYPE> $ARGLIST) = ...; + ... + (Process $P) = ...; + - pattern: | + $ARGLIST.add(...); + metadata: + category: security + technology: + - java + cwe: + - "CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')" + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + references: + - https://owasp.org/Top10/A03_2021-Injection + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM +- id: java.lang.security.audit.tainted-env-from-http-request.tainted-env-from-http-request + message: >- + Detected input from a HTTPServletRequest going into the environment variables of an 'exec' command. + Instead, call the command with user-supplied arguments by using the overloaded method with one String array as the argument. + `exec({"command", "arg1", "arg2"})`. + languages: [java] + severity: ERROR + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - pattern: | + (HttpServletRequest $REQ) + - patterns: # this pattern is a hack to get the rule to recognize `map` as tainted source when `cookie.getValue(user_input)` is used. + - pattern-inside: | + (javax.servlet.http.Cookie[] $COOKIES) = (HttpServletRequest $REQ).getCookies(...); + ... + for (javax.servlet.http.Cookie $COOKIE: $COOKIES) { + ... + } + - pattern: | + $COOKIE.getValue(...) + pattern-sinks: + - patterns: + - pattern: (java.lang.Runtime $R).exec($CMD, $ENV_ARGS, ...); + - focus-metavariable: $ENV_ARGS + metadata: + category: security + technology: + - java + cwe: + - "CWE-454: External Initialization of Trusted Variables or Data Stores" + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + references: + - https://owasp.org/Top10/A03_2021-Injection + cwe2022-top25: false + cwe2021-top25: false + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM +- id: java.lang.security.audit.tainted-ldapi-from-http-request.tainted-ldapi-from-http-request + message: >- + Detected input from a HTTPServletRequest going into an LDAP query. + This could lead to LDAP injection if the input is not properly sanitized, + which could result in attackers modifying objects in the LDAP tree structure. + Ensure data passed to an LDAP query is not controllable or properly sanitize + the data. + metadata: + cwe: + - "CWE-90: Improper Neutralization of Special Elements used in an LDAP Query ('LDAP Injection')" + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + references: + - https://sensei.securecodewarrior.com/recipes/scw%3Ajava%3ALDAP-injection + category: security + technology: + - java + subcategory: + - vuln + impact: MEDIUM + likelihood: MEDIUM + confidence: MEDIUM + severity: WARNING + languages: [java] + mode: taint + pattern-sources: + - patterns: + - pattern: (HttpServletRequest $REQ) + pattern-sinks: + - patterns: + - pattern-either: + - pattern: | + (javax.naming.directory.InitialDirContext $IDC).search(...) + - pattern: | + (javax.naming.directory.DirContext $CTX).search(...) + - pattern-not: | + (javax.naming.directory.InitialDirContext $IDC).search($Y, "...", ...) + - pattern-not: | + (javax.naming.directory.DirContext $CTX).search($Y, "...", ...) +- id: java.lang.security.audit.tainted-session-from-http-request.tainted-session-from-http-request + message: >- + Detected input from a HTTPServletRequest going into a session command, like `setAttribute`. + User input into such a command could lead to an attacker inputting malicious code into your session + parameters, blurring the line between what's trusted and untrusted, and therefore leading to a trust + boundary violation. + This could lead to programmers trusting unvalidated data. + Instead, thoroughly sanitize user input before passing it + into such function calls. + languages: [java] + severity: WARNING + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - patterns: + - pattern: | + (HttpServletRequest $REQ).$FUNC(...) + - pattern-not: | + (HttpServletRequest $REQ).getSession() + - patterns: # this pattern is a hack to get the rule to recognize `map` as tainted source when `cookie. getValue(user_input)` is used. + - pattern-inside: | + (javax.servlet.http.Cookie[] $COOKIES) = (HttpServletRequest $REQ).getCookies(...); + ... + for (javax.servlet.http.Cookie $COOKIE: $COOKIES) { + ... + } + - pattern: | + $COOKIE.getValue(...) + - patterns: # use this pattern to catch cases where tainted array values are assigned to a variable (not caught by taint) + - pattern-inside: | + $TYPE[] $VALS = (HttpServletRequest $REQ).$GETFUNC(... ); + ... + - pattern: | + $PARAM = $VALS[$INDEX]; + - patterns: # use this pattern to catch cases where request headers are later decoded + - pattern-inside: | + $HEADERS = (HttpServletRequest $REQ).getHeaders(...); + ... + $PARAM = $HEADERS.$FUNC(...); + ... + - pattern: | + java.net.URLDecoder.decode($PARAM, ...) + pattern-sinks: + - patterns: + - pattern: (HttpServletRequest $REQ).getSession().$FUNC($NAME, $VALUE); + - metavariable-regex: + metavariable: $FUNC + regex: ^(putValue|setAttribute)$ + - focus-metavariable: $VALUE + options: + interfile: true + metadata: + category: security + technology: + - java + cwe: + - 'CWE-501: Trust Boundary Violation' + owasp: + - A04:2021 - Insecure Design + references: + - https://owasp.org/Top10/A04_2021-Insecure_Design + subcategory: + - vuln + impact: MEDIUM + likelihood: MEDIUM + confidence: MEDIUM + interfile: true +- id: java.lang.security.audit.tainted-xpath-from-http-request.tainted-xpath-from-http-request + message: >- + Detected input from a HTTPServletRequest going into a XPath evaluate or compile command. This could + lead to xpath injection if variables passed into the evaluate or compile commands are not properly + sanitized. + Xpath injection could lead to unauthorized access to sensitive information in XML documents. + Instead, thoroughly sanitize user input or use parameterized xpath queries if you can. + languages: [java] + severity: WARNING + mode: taint + pattern-sources: + - patterns: + - pattern: | + (HttpServletRequest $REQ).$FUNC(...) + pattern-sinks: + - patterns: + - pattern-either: + - pattern: | + (javax.xml.xpath.XPath $XP).evaluate(...) + - pattern: | + (javax.xml.xpath.XPath $XP).compile(...).evaluate(...) + metadata: + category: security + technology: + - java + cwe: + - "CWE-643: Improper Neutralization of Data within XPath Expressions ('XPath Injection')" + owasp: + - A03:2021 - Injection + references: + - https://owasp.org/Top10/A03_2021-Injection + subcategory: + - vuln + likelihood: HIGH + impact: MEDIUM + confidence: MEDIUM +- id: java.lang.security.audit.unsafe-reflection.unsafe-reflection + patterns: + - pattern: | + Class.forName($CLASS,...) + - pattern-not: | + Class.forName("...",...) + - pattern-not-inside: | + $CLASS = "..."; + ... + message: >- + If an attacker can supply values that the application then uses to determine which + class to instantiate or which method to invoke, + the potential exists for the attacker to create control flow paths through the + application + that were not intended by the application developers. + This attack vector may allow the attacker to bypass authentication or access control + checks + or otherwise cause the application to behave in an unexpected manner. + metadata: + cwe: + - "CWE-470: Use of Externally-Controlled Input to Select Classes or Code ('Unsafe Reflection')" + owasp: + - A03:2021 - Injection + source-rule-url: https://owasp.org/www-community/vulnerabilities/Unsafe_use_of_Reflection + category: security + technology: + - java + references: + - https://owasp.org/Top10/A03_2021-Injection + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + severity: WARNING + languages: + - java +- id: java.lang.security.audit.unvalidated-redirect.unvalidated-redirect + message: >- + Application redirects to a destination URL specified by a user-supplied + parameter that is not validated. This could direct users to malicious locations. + Consider using an allowlist to validate URLs. + metadata: + cwe: + - "CWE-601: URL Redirection to Untrusted Site ('Open Redirect')" + owasp: + - A01:2021 - Broken Access Control + source-rule-url: https://find-sec-bugs.github.io/bugs.htm#UNVALIDATED_REDIRECT + asvs: + section: 'V5: Validation, Sanitization and Encoding Verification Requirements' + control_id: 5.1.5 Open Redirect + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x13-V5-Validation-Sanitization-Encoding.md#v51-input-validation-requirements + version: '4' + category: security + technology: + - java + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - vuln + impact: LOW + likelihood: MEDIUM + confidence: MEDIUM + severity: WARNING + languages: [java] + pattern-either: + - pattern: | + $X $METHOD(...,HttpServletResponse $RES,...,String $URL,...) { + ... + $RES.sendRedirect($URL); + ... + } + - pattern: | + $X $METHOD(...,String $URL,...,HttpServletResponse $RES,...) { + ... + $RES.sendRedirect($URL); + ... + } + - pattern: | + $X $METHOD(...,HttpServletRequest $REQ,...,HttpServletResponse $RES,...) { + ... + String $URL = $REQ.getParameter(...); + ... + $RES.sendRedirect($URL); + ... + } + - pattern: | + $X $METHOD(...,HttpServletResponse $RES,...,HttpServletRequest $REQ,...) { + ... + String $URL = $REQ.getParameter(...); + ... + $RES.sendRedirect($URL); + ... + } + - pattern: | + $X $METHOD(...,String $URL,...) { + ... + HttpServletResponse $RES = ...; + ... + $RES.sendRedirect($URL); + ... + } + - pattern: | + $X $METHOD(...,HttpServletRequest $REQ,...,HttpServletResponse $RES,...) { + ... + $RES.sendRedirect($REQ.getParameter(...)); + ... + } + - pattern: | + $X $METHOD(...,HttpServletResponse $RES,...,HttpServletRequest $REQ,...) { + ... + $RES.sendRedirect($REQ.getParameter(...)); + ... + } + - pattern: | + $X $METHOD(...,HttpServletResponse $RES,...,String $URL,...) { + ... + $RES.addHeader("Location",$URL); + ... + } + - pattern: | + $X $METHOD(...,String $URL,...,HttpServletResponse $RES,...) { + ... + $RES.addHeader("Location",$URL); + ... + } + - pattern: | + $X $METHOD(...,HttpServletRequest $REQ,...,HttpServletResponse $RES,...) { + ... + String $URL = $REQ.getParameter(...); + ... + $RES.addHeader("Location",$URL); + ... + } + - pattern: | + $X $METHOD(...,HttpServletResponse $RES,...,HttpServletRequest $REQ,...) { + ... + String $URL = $REQ.getParameter(...); + ... + $RES.addHeader("Location",$URL); + ... + } + - pattern: | + $X $METHOD(...,String $URL,...) { + ... + HttpServletResponse $RES = ...; + ... + $RES.addHeader("Location",$URL); + ... + } + - pattern: | + $X $METHOD(...,HttpServletRequest $REQ,...,HttpServletResponse $RES,...) { + ... + $RES.addHeader("Location",$REQ.getParameter(...)); + ... + } + - pattern: |- + $X $METHOD(...,HttpServletResponse $RES,...,HttpServletRequest $REQ,...) { + ... + $RES.addHeader("Location",$REQ.getParameter(...)); + ... + } +- id: java.lang.security.audit.url-rewriting.url-rewriting + message: >- + URL rewriting has significant security risks. + Since session ID appears in the URL, it may be easily seen by third parties. + metadata: + cwe: + - 'CWE-200: Exposure of Sensitive Information to an Unauthorized Actor' + owasp: + - A01:2021 - Broken Access Control + source-rule-url: https://find-sec-bugs.github.io/bugs.htm#URL_REWRITING + category: security + technology: + - java + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + cwe2021-top25: true + subcategory: + - vuln + likelihood: LOW + impact: MEDIUM + confidence: LOW + severity: WARNING + languages: [java] + pattern-either: + - pattern: | + $X $METHOD(...,HttpServletResponse $RES,...) { + ... + $RES.encodeURL(...); + ... + } + - pattern: | + $X $METHOD(...,HttpServletResponse $RES,...) { + ... + $RES.encodeUrl(...); + ... + } + - pattern: | + $X $METHOD(...,HttpServletResponse $RES,...) { + ... + $RES.encodeRedirectURL(...); + ... + } + - pattern: | + $X $METHOD(...,HttpServletResponse $RES,...) { + ... + $RES.encodeRedirectUrl(...); + ... + } + - pattern: | + $X $METHOD(...) { + ... + HttpServletResponse $RES = ...; + ... + $RES.encodeURL(...); + ... + } + - pattern: | + $X $METHOD(...) { + ... + HttpServletResponse $RES = ...; + ... + $RES.encodeUrl(...); + ... + } + - pattern: | + $X $METHOD(...) { + ... + HttpServletResponse $RES = ...; + ... + $RES.encodeRedirectURL(...); + ... + } + - pattern: |- + $X $METHOD(...) { + ... + HttpServletResponse $RES = ...; + ... + $RES.encodeRedirectUrl(...); + ... + } +- id: java.lang.security.audit.weak-ssl-context.weak-ssl-context + metadata: + cwe: + - 'CWE-326: Inadequate Encryption Strength' + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + source_rule_url: https://find-sec-bugs.github.io/bugs.htm#SSL_CONTEXT + references: + - https://tools.ietf.org/html/rfc7568 + - https://tools.ietf.org/id/draft-ietf-tls-oldversions-deprecate-02.html + category: security + technology: + - java + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: HIGH + message: >- + An insecure SSL context was detected. TLS versions 1.0, 1.1, and all SSL versions + are considered weak encryption and are deprecated. + Use SSLContext.getInstance("TLSv1.2") for the best security. + severity: WARNING + languages: [java] + patterns: + - pattern-not: SSLContext.getInstance("TLSv1.3") + - pattern-not: SSLContext.getInstance("TLSv1.2") + - pattern: SSLContext.getInstance("...") + fix-regex: + regex: (.*?)\.getInstance\(.*?\) + replacement: \1.getInstance("TLSv1.2") +- id: java.lang.security.audit.xml-decoder.xml-decoder + message: >- + XMLDecoder should not be used to parse untrusted data. + Deserializing user input can lead to arbitrary code execution. + Use an alternative and explicitly disable external entities. + See https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html + for alternatives and vulnerability prevention. + metadata: + cwe: + - 'CWE-611: Improper Restriction of XML External Entity Reference' + owasp: + - A04:2017 - XML External Entities (XXE) + - A05:2021 - Security Misconfiguration + source-rule-url: https://find-sec-bugs.github.io/bugs.htm#XML_DECODER + references: + - https://semgrep.dev/blog/2022/xml-security-in-java + - https://semgrep.dev/docs/cheat-sheets/java-xxe/ + - https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html + category: security + technology: + - java + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH + confidence: LOW + severity: WARNING + languages: [java] + patterns: + - pattern: | + $X $METHOD(...) { + ... + new XMLDecoder(...); + ... + } + - pattern-not: | + $X $METHOD(...) { + ... + new XMLDecoder("..."); + ... + } + - pattern-not: |- + $X $METHOD(...) { + ... + String $STR = "..."; + ... + new XMLDecoder($STR); + ... + } +- id: java.lang.security.audit.xss.jsf.autoescape-disabled.autoescape-disabled + message: >- + Detected an element with disabled HTML escaping. If external + data can reach this, this is a cross-site scripting (XSS) + vulnerability. Ensure no external data can reach here, or + remove 'escape=false' from this element. + metadata: + owasp: 'A07:2017 - Cross-Site Scripting (XSS)' + cwe: + - 'CWE-150: Improper Neutralization of Escape, Meta, or Control Sequences' + references: + - https://stackoverflow.com/a/7442668 + category: security + technology: + - jsf + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + pattern-regex: |- + .*escape.*?=.*?false.* + paths: + include: + - '*.html' + - '*.xhtml' + languages: [regex] + severity: WARNING +- id: java.lang.security.audit.xss.jsp.no-scriptlets.no-scriptlets + message: >- + JSP scriptlet detected. Scriptlets are difficult to use securely and + are considered bad practice. See https://stackoverflow.com/a/3180202. + Instead, consider migrating to JSF or using the Expression Language + '${...}' with the escapeXml function in your JSP files. + metadata: + owasp: + - A03:2021 - Injection + cwe: + - 'CWE-116: Improper Encoding or Escaping of Output' + references: + - https://stackoverflow.com/a/3180202 + - https://stackoverflow.com/a/4948856 + category: security + technology: + - jsp + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + pattern-regex: |- + \<\%[^\@].* + paths: + include: + - '*.jsp' + languages: [regex] + severity: WARNING +- id: java.lang.security.audit.xss.jsp.use-escapexml.use-escapexml + message: >- + Detected an Expression Language segment that does not escape + output. This is dangerous because if any data in this expression + can be controlled externally, it is a cross-site scripting + vulnerability. Instead, use the 'escapeXml' function from + the JSTL taglib. See https://www.tutorialspoint.com/jsp/jstl_function_escapexml.htm + for more information. + metadata: + owasp: + - A03:2021 - Injection + cwe: + - 'CWE-116: Improper Encoding or Escaping of Output' + references: + - https://www.tutorialspoint.com/jsp/jstl_function_escapexml.htm + - https://stackoverflow.com/a/4948856 + - https://stackoverflow.com/a/3180202 + category: security + technology: + - jsp + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + pattern-regex: \$\{(?!.*escapeXml).*\} + paths: + include: + - '*.jsp' + languages: [regex] + severity: WARNING +- id: java.lang.security.audit.xss.jsp.use-jstl-escaping.use-jstl-escaping + message: >- + Detected an Expression Language segment in a tag that does not escape + output. This is dangerous because if any data in this expression + can be controlled externally, it is a cross-site scripting + vulnerability. Instead, use the 'out' tag from the JSTL taglib + to escape this expression. + See https://www.tutorialspoint.com/jsp/jstl_core_out_tag.htm + for more information. + metadata: + owasp: + - A03:2021 - Injection + cwe: + - 'CWE-116: Improper Encoding or Escaping of Output' + references: + - https://www.tutorialspoint.com/jsp/jstl_core_out_tag.htm + - https://stackoverflow.com/a/4948856 + - https://stackoverflow.com/a/3180202 + category: security + technology: + - jsp + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + pattern-regex: <(?![A-Za-z0-9]+:out).*?\$\{.*?\}.*> + paths: + include: + - '*.jsp' + languages: [regex] + severity: WARNING +- id: java.lang.security.audit.xss.no-direct-response-writer.no-direct-response-writer + message: Detected a request with potential user-input going into a OutputStream + or Writer object. This bypasses any view or template environments, + including HTML escaping, which may expose this application to cross-site + scripting (XSS) vulnerabilities. Consider using a view technology such as + JavaServer Faces (JSFs) which automatically escapes HTML views. + severity: WARNING + options: + interfile: true + metadata: + likelihood: HIGH + impact: MEDIUM + confidence: MEDIUM + category: security + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation + ('Cross-site Scripting')" + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + references: + - https://www3.ntu.edu.sg/home/ehchua/programming/java/JavaServerFaces.html + subcategory: + - vuln + technology: + - java + - servlets + interfile: true + license: proprietary license - copyright © Semgrep, Inc. + languages: + - java + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - pattern: | + (HttpServletRequest $REQ).$REQFUNC(...) + - pattern: | + (ServletRequest $REQ).$REQFUNC(...) + - metavariable-regex: + metavariable: $REQFUNC + regex: (getInputStream|getParameter|getParameterMap|getParameterValues|getReader|getCookies|getHeader|getHeaderNames|getHeaders|getPart|getParts|getQueryString) + pattern-sinks: + - patterns: + - pattern-either: + - pattern: | + (HttpServletResponse $RESPONSE).getWriter(...).$WRITE(...) + - pattern: > + (HttpServletResponse + $RESPONSE).getOutputStream(...).$WRITE(...) + - pattern: | + (java.io.PrintWriter $WRITER).$WRITE(...) + - pattern: | + (PrintWriter $WRITER).$WRITE(...) + - pattern: | + (javax.servlet.ServletOutputStream $WRITER).$WRITE(...) + - pattern: | + (ServletOutputStream $WRITER).$WRITE(...) + - pattern: | + (java.io.OutputStream $WRITER).$WRITE(...) + - pattern: | + (OutputStream $WRITER).$WRITE(...) + pattern-sanitizers: + - pattern-either: + - pattern: Encode.forHtml(...) + - pattern: (PolicyFactory $POLICY).sanitize(...) + - pattern: (AntiSamy $AS).scan(...) + - pattern: JSoup.clean(...) + - pattern: org.apache.commons.lang.StringEscapeUtils.escapeHtml(...) + - pattern: org.springframework.web.util.HtmlUtils.htmlEscape(...) + - pattern: org.owasp.esapi.ESAPI.encoder().encodeForHTML(...) +- id: java.lang.security.audit.xssrequestwrapper-is-insecure.xssrequestwrapper-is-insecure + metadata: + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + source-rule-url: https://find-sec-bugs.github.io/bugs.htm#XSS_REQUEST_WRAPPER + category: security + technology: + - java + references: + - https://owasp.org/Top10/A03_2021-Injection + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + message: >- + It looks like you're using an implementation of XSSRequestWrapper from dzone. + (https://www.javacodegeeks.com/2012/07/anti-cross-site-scripting-xss-filter.html) + The XSS filtering in this code is not secure and can be bypassed by malicious + actors. + It is recommended to use a stack that automatically escapes in your view or templates + instead of filtering yourself. + severity: WARNING + languages: + - java + pattern-either: + - pattern: | + class XSSRequestWrapper extends HttpServletRequestWrapper { + ... + } + - pattern: |- + $P = $X.compile("", $X.CASE_INSENSITIVE); + $V = $P.matcher(...).replaceAll(""); +- id: java.lang.security.audit.xxe.documentbuilderfactory-disallow-doctype-decl-false.documentbuilderfactory-disallow-doctype-decl-false + severity: ERROR + metadata: + cwe: + - 'CWE-611: Improper Restriction of XML External Entity Reference' + owasp: + - A04:2017 - XML External Entities (XXE) + - A05:2021 - Security Misconfiguration + asvs: + section: V5 Validation, Sanitization and Encoding + control_id: 5.5.2 Insecue XML Deserialization + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x13-V5-Validation-Sanitization-Encoding.md#v55-deserialization-prevention + version: '4' + references: + - https://semgrep.dev/blog/2022/xml-security-in-java + - https://semgrep.dev/docs/cheat-sheets/java-xxe/ + - https://blog.sonarsource.com/secure-xml-processor + - https://xerces.apache.org/xerces2-j/features.html + category: security + technology: + - java + - xml + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: LOW + impact: HIGH + confidence: HIGH + message: >- + DOCTYPE declarations are enabled for $DBFACTORY. + Without prohibiting external entity declarations, this is vulnerable to XML external entity attacks. + Disable this by setting the feature "http://apache.org/xml/features/disallow-doctype-decl" to true. + Alternatively, allow DOCTYPE declarations and only prohibit external entities declarations. + This can be done by setting the features "http://xml.org/sax/features/external-general-entities" and + "http://xml.org/sax/features/external-parameter-entities" to false. + patterns: + - pattern: $DBFACTORY.setFeature("http://apache.org/xml/features/disallow-doctype-decl", false); + - pattern-not-inside: | + $RETURNTYPE $METHOD(...){ + ... + $DBF.setFeature("http://xml.org/sax/features/external-general-entities", false); + ... + $DBF.setFeature("http://xml.org/sax/features/external-parameter-entities", false); + ... + } + - pattern-not-inside: | + $RETURNTYPE $METHOD(...){ + ... + $DBF.setFeature("http://xml.org/sax/features/external-parameter-entities", false); + ... + $DBF.setFeature("http://xml.org/sax/features/external-general-entities", false); + ... + } + - pattern-not-inside: | + $RETURNTYPE $METHOD(...){ + ... + $DBF.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, ""); + ... + $DBF.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, ""); + ... + } + - pattern-not-inside: | + $RETURNTYPE $METHOD(...){ + ... + $DBF.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, ""); + ... + $DBF.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, ""); + ... + } + languages: + - java +- id: java.lang.security.audit.xxe.documentbuilderfactory-disallow-doctype-decl-missing.documentbuilderfactory-disallow-doctype-decl-missing + severity: ERROR + metadata: + cwe: + - "CWE-611: Improper Restriction of XML External Entity Reference" + owasp: + - A04:2017 - XML External Entities (XXE) + - A05:2021 - Security Misconfiguration + asvs: + section: V5 Validation, Sanitization and Encoding + control_id: 5.5.2 Insecue XML Deserialization + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x13-V5-Validation-Sanitization-Encoding.md#v55-deserialization-prevention + version: "4" + references: + - https://semgrep.dev/blog/2022/xml-security-in-java + - https://semgrep.dev/docs/cheat-sheets/java-xxe/ + - https://blog.sonarsource.com/secure-xml-processor + - https://xerces.apache.org/xerces2-j/features.html + category: security + technology: + - java + - xml + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: LOW + impact: HIGH + confidence: HIGH + message: DOCTYPE declarations are enabled for this DocumentBuilderFactory. This + is vulnerable to XML external entity attacks. Disable this by setting the + feature "http://apache.org/xml/features/disallow-doctype-decl" to true. + Alternatively, allow DOCTYPE declarations and only prohibit external + entities declarations. This can be done by setting the features + "http://xml.org/sax/features/external-general-entities" and + "http://xml.org/sax/features/external-parameter-entities" to false. + mode: taint + pattern-sources: + - by-side-effect: true + patterns: + - pattern-either: + - pattern: | + $FACTORY = DocumentBuilderFactory.newInstance(); + - patterns: + - pattern: $FACTORY + - pattern-inside: | + class $C { + ... + $V $FACTORY = DocumentBuilderFactory.newInstance(); + ... + } + - pattern-not-inside: > + class $C { + ... + $V $FACTORY = DocumentBuilderFactory.newInstance(); + static { + ... + $FACTORY.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + ... + } + ... + } + - pattern-not-inside: > + class $C { + ... + $V $FACTORY = DocumentBuilderFactory.newInstance(); + static { + ... + $FACTORY.setFeature("http://xml.org/sax/features/external-parameter-entities", false); + ... + $FACTORY.setFeature("http://xml.org/sax/features/external-general-entities", false); + ... + } + ... + } + - pattern-not-inside: > + class $C { + ... + $V $FACTORY = DocumentBuilderFactory.newInstance(); + static { + ... + $FACTORY.setFeature("http://xml.org/sax/features/external-general-entities", false); + ... + $FACTORY.setFeature("http://xml.org/sax/features/external-parameter-entities", false); + ... + } + ... + } + pattern-sinks: + - patterns: + - pattern: $FACTORY.newDocumentBuilder(); + pattern-sanitizers: + - by-side-effect: true + pattern-either: + - patterns: + - pattern-either: + - pattern: > + $FACTORY.setFeature("http://apache.org/xml/features/disallow-doctype-decl", + true); + - pattern: > + $FACTORY.setFeature("http://xml.org/sax/features/external-general-entities", + false); + + ... + + $FACTORY.setFeature("http://xml.org/sax/features/external-parameter-entities", false); + - pattern: > + $FACTORY.setFeature("http://xml.org/sax/features/external-parameter-entities", + false); + + ... + + $FACTORY.setFeature("http://xml.org/sax/features/external-general-entities", false); + - focus-metavariable: $FACTORY + - patterns: + - pattern-either: + - pattern-inside: > + class $C { + ... + $T $M(...) { + ... + $FACTORY.setFeature("http://apache.org/xml/features/disallow-doctype-decl", + true); + ... + } + ... + } + - pattern-inside: > + class $C { + ... + $T $M(...) { + ... + $FACTORY.setFeature("http://xml.org/sax/features/external-general-entities", false); + ... + $FACTORY.setFeature("http://xml.org/sax/features/external-parameter-entities", false); + ... + } + ... + } + - pattern-inside: > + class $C { + ... + $T $M(...) { + ... + $FACTORY.setFeature("http://xml.org/sax/features/external-parameter-entities", false); + ... + $FACTORY.setFeature("http://xml.org/sax/features/external-general-entities",false); + ... + } + ... + } + - pattern: $M($X) + - focus-metavariable: $X + fix: > + $FACTORY.setFeature("http://apache.org/xml/features/disallow-doctype-decl", + true); + + $FACTORY.newDocumentBuilder(); + languages: + - java +- id: java.lang.security.audit.xxe.documentbuilderfactory-external-general-entities-true.documentbuilderfactory-external-general-entities-true + severity: ERROR + metadata: + cwe: + - 'CWE-611: Improper Restriction of XML External Entity Reference' + owasp: + - A04:2017 - XML External Entities (XXE) + - A05:2021 - Security Misconfiguration + asvs: + section: V5 Validation, Sanitization and Encoding + control_id: 5.5.2 Insecue XML Deserialization + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x13-V5-Validation-Sanitization-Encoding.md#v55-deserialization-prevention + version: '4' + references: + - https://semgrep.dev/blog/2022/xml-security-in-java + - https://semgrep.dev/docs/cheat-sheets/java-xxe/ + - https://blog.sonarsource.com/secure-xml-processor + category: security + technology: + - java + - xml + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: LOW + impact: HIGH + confidence: HIGH + message: >- + External entities are allowed for $DBFACTORY. + This is vulnerable to XML external entity attacks. Disable this by setting the feature "http://xml.org/sax/features/external-general-entities" + to false. + pattern: $DBFACTORY.setFeature("http://xml.org/sax/features/external-general-entities", true); + fix: $DBFACTORY.setFeature("http://xml.org/sax/features/external-general-entities", false); + languages: + - java +- id: java.lang.security.audit.xxe.documentbuilderfactory-external-parameter-entities-true.documentbuilderfactory-external-parameter-entities-true + severity: ERROR + metadata: + cwe: + - 'CWE-611: Improper Restriction of XML External Entity Reference' + owasp: + - A04:2017 - XML External Entities (XXE) + - A05:2021 - Security Misconfiguration + asvs: + section: V5 Validation, Sanitization and Encoding + control_id: 5.5.2 Insecue XML Deserialization + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x13-V5-Validation-Sanitization-Encoding.md#v55-deserialization-prevention + version: '4' + references: + - https://semgrep.dev/blog/2022/xml-security-in-java + - https://semgrep.dev/docs/cheat-sheets/java-xxe/ + - https://blog.sonarsource.com/secure-xml-processor + category: security + technology: + - java + - xml + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: LOW + impact: HIGH + confidence: HIGH + message: >- + External entities are allowed for $DBFACTORY. + This is vulnerable to XML external entity attacks. Disable this by setting the feature "http://xml.org/sax/features/external-parameter-entities" + to false. + pattern: $DBFACTORY.setFeature("http://xml.org/sax/features/external-parameter-entities", true); + fix: $DBFACTORY.setFeature("http://xml.org/sax/features/external-parameter-entities", false); + languages: + - java +- id: java.lang.security.audit.xxe.saxparserfactory-disallow-doctype-decl-missing.saxparserfactory-disallow-doctype-decl-missing + severity: ERROR + metadata: + cwe: + - "CWE-611: Improper Restriction of XML External Entity Reference" + owasp: + - A04:2017 - XML External Entities (XXE) + - A05:2021 - Security Misconfiguration + asvs: + section: V5 Validation, Sanitization and Encoding + control_id: 5.5.2 Insecue XML Deserialization + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x13-V5-Validation-Sanitization-Encoding.md#v55-deserialization-prevention + version: "4" + references: + - https://semgrep.dev/blog/2022/xml-security-in-java + - https://semgrep.dev/docs/cheat-sheets/java-xxe/ + - https://blog.sonarsource.com/secure-xml-processor + - https://xerces.apache.org/xerces2-j/features.html + category: security + technology: + - java + - xml + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: LOW + impact: HIGH + confidence: HIGH + message: DOCTYPE declarations are enabled for this SAXParserFactory. This + is vulnerable to XML external entity attacks. Disable this by setting the + feature `http://apache.org/xml/features/disallow-doctype-decl` to true. + Alternatively, allow DOCTYPE declarations and only prohibit external + entities declarations. This can be done by setting the features + `http://xml.org/sax/features/external-general-entities` and + `http://xml.org/sax/features/external-parameter-entities` to false. + NOTE - The previous links are not meant to be clicked. They are the + literal config key values that are supposed to be used to disable these + features. For more information, see https://semgrep.dev/docs/cheat-sheets/java-xxe/#3a-documentbuilderfactory. + mode: taint + pattern-sources: + - by-side-effect: true + patterns: + - pattern-either: + - pattern: | + $FACTORY = SAXParserFactory.newInstance(); + - patterns: + - pattern: $FACTORY + - pattern-inside: | + class $C { + ... + $V $FACTORY = SAXParserFactory.newInstance(); + ... + } + - pattern-not-inside: > + class $C { + ... + $V $FACTORY = SAXParserFactory.newInstance(); + static { + ... + $FACTORY.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + ... + } + ... + } + - pattern-not-inside: > + class $C { + ... + $V $FACTORY = SAXParserFactory.newInstance(); + static { + ... + $FACTORY.setFeature("http://xml.org/sax/features/external-parameter-entities", false); + ... + $FACTORY.setFeature("http://xml.org/sax/features/external-general-entities", false); + ... + } + ... + } + - pattern-not-inside: > + class $C { + ... + $V $FACTORY = SAXParserFactory.newInstance(); + static { + ... + $FACTORY.setFeature("http://xml.org/sax/features/external-general-entities", false); + ... + $FACTORY.setFeature("http://xml.org/sax/features/external-parameter-entities", false); + ... + } + ... + } + pattern-sinks: + - patterns: + - pattern: $FACTORY.newSAXParser(); + pattern-sanitizers: + - by-side-effect: true + pattern-either: + - patterns: + - pattern-either: + - pattern: > + $FACTORY.setFeature("http://apache.org/xml/features/disallow-doctype-decl", + true); + - pattern: > + $FACTORY.setFeature("http://xml.org/sax/features/external-general-entities", + false); + + ... + + $FACTORY.setFeature("http://xml.org/sax/features/external-parameter-entities", false); + - pattern: > + $FACTORY.setFeature("http://xml.org/sax/features/external-parameter-entities", + false); + + ... + + $FACTORY.setFeature("http://xml.org/sax/features/external-general-entities", false); + - focus-metavariable: $FACTORY + - patterns: + - pattern-either: + - pattern-inside: > + class $C { + ... + $T $M(...) { + ... + $FACTORY.setFeature("http://apache.org/xml/features/disallow-doctype-decl", + true); + ... + } + ... + } + - pattern-inside: > + class $C { + ... + $T $M(...) { + ... + $FACTORY.setFeature("http://xml.org/sax/features/external-general-entities", false); + ... + $FACTORY.setFeature("http://xml.org/sax/features/external-parameter-entities", false); + ... + } + ... + } + - pattern-inside: > + class $C { + ... + $T $M(...) { + ... + $FACTORY.setFeature("http://xml.org/sax/features/external-parameter-entities", false); + ... + $FACTORY.setFeature("http://xml.org/sax/features/external-general-entities",false); + ... + } + ... + } + - pattern: $M($X) + - focus-metavariable: $X + fix: > + $FACTORY.setFeature("http://apache.org/xml/features/disallow-doctype-decl", + true); + + $FACTORY.newSAXParser(); + languages: + - java +- id: java.lang.security.audit.xxe.transformerfactory-dtds-not-disabled.transformerfactory-dtds-not-disabled + severity: ERROR + metadata: + cwe: + - "CWE-611: Improper Restriction of XML External Entity Reference" + owasp: + - A04:2017 - XML External Entities (XXE) + - A05:2021 - Security Misconfiguration + asvs: + section: V5 Validation, Sanitization and Encoding + control_id: 5.5.2 Insecue XML Deserialization + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x13-V5-Validation-Sanitization-Encoding.md#v55-deserialization-prevention + version: "4" + references: + - https://semgrep.dev/blog/2022/xml-security-in-java + - https://semgrep.dev/docs/cheat-sheets/java-xxe/ + - https://blog.sonarsource.com/secure-xml-processor + - https://xerces.apache.org/xerces2-j/features.html + category: security + technology: + - java + - xml + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: LOW + impact: HIGH + confidence: HIGH + message: DOCTYPE declarations are enabled for this TransformerFactory. This + is vulnerable to XML external entity attacks. Disable this by setting the + attributes "accessExternalDTD" and "accessExternalStylesheet" to "". + mode: taint + pattern-sources: + - by-side-effect: true + patterns: + - pattern-either: + - pattern: | + $FACTORY = TransformerFactory.newInstance(); + - patterns: + - pattern: $FACTORY + - pattern-inside: | + class $C { + ... + $V $FACTORY = TransformerFactory.newInstance(); + ... + } + - pattern-not-inside: > + class $C { + ... + $V $FACTORY = TransformerFactory.newInstance(); + static { + ... + $FACTORY.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, ""); + ... + $FACTORY.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, ""); + ... + } + ... + } + - pattern-not-inside: > + class $C { + ... + $V $FACTORY = TransformerFactory.newInstance(); + static { + ... + $FACTORY.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, ""); + ... + $FACTORY.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, ""); + ... + } + ... + } + - pattern-not-inside: > + class $C { + ... + $V $FACTORY = TransformerFactory.newInstance(); + static { + ... + $FACTORY.setAttribute("=~/.*accessExternalDTD.*/", ""); + ... + $FACTORY.setAttribute("=~/.*accessExternalStylesheet.*/", ""); + ... + } + ... + } + - pattern-not-inside: > + class $C { + ... + $V $FACTORY = TransformerFactory.newInstance(); + static { + ... + $FACTORY.setAttribute("=~/.*accessExternalStylesheet.*/", ""); + ... + $FACTORY.setAttribute("=~/.*accessExternalDTD.*/", ""); + ... + } + ... + } + pattern-sinks: + - patterns: + - pattern: $FACTORY.newTransformer(...); + pattern-sanitizers: + - by-side-effect: true + pattern-either: + - patterns: + - pattern-either: + - pattern: > + $FACTORY.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, ""); + ... + + $FACTORY.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, ""); + - pattern: > + $FACTORY.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, ""); + + ... + + $FACTORY.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, ""); + - pattern: > + $FACTORY.setAttribute("=~/.*accessExternalStylesheet.*/", ""); + ... + + $FACTORY.setAttribute("=~/.*accessExternalDTD.*/", ""); + - pattern: > + $FACTORY.setAttribute("=~/.*accessExternalDTD.*/", ""); + + ... + + $FACTORY.setAttribute("=~/.*accessExternalStylesheet.*/", ""); + - focus-metavariable: $FACTORY + - patterns: + - pattern-either: + - pattern-inside: > + class $C { + ... + $T $M(...) { + ... + $FACTORY.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, ""); + ... + $FACTORY.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, ""); + ... + } + ... + } + - pattern-inside: > + class $C { + ... + $T $M(...) { + ... + $FACTORY.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, ""); + ... + $FACTORY.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, ""); + ... + } + ... + } + - pattern-inside: > + class $C { + ... + $T $M(...) { + ... + $FACTORY.setAttribute("=~/.*accessExternalStylesheet.*/", ""); + ... + $FACTORY.setAttribute("=~/.*accessExternalDTD.*/", ""); + ... + } + ... + } + - pattern-inside: > + class $C { + ... + $T $M(...) { + ... + $FACTORY.setAttribute("=~/.*accessExternalDTD.*/", ""); + ... + $FACTORY.setAttribute("=~/.*accessExternalStylesheet.*/", ""); + ... + } + ... + } + - pattern: $M($X) + - focus-metavariable: $X + fix: > + $FACTORY.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, ""); + $FACTORY.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, ""); + + $FACTORY.newTransformer(...); + languages: + - java +- id: java.lang.security.do-privileged-use.do-privileged-use + severity: WARNING + languages: + - java + metadata: + cwe: + - 'CWE-269: Improper Privilege Management' + references: + - https://docs.oracle.com/javase/8/docs/technotes/guides/security/doprivileged.html + - https://wiki.sei.cmu.edu/confluence/display/java/Privilege+Escalation + - http://phrack.org/papers/escaping_the_java_sandbox.html + category: security + technology: + - java + owasp: + - A04:2021 - Insecure Design + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + message: >- + Marking code as privileged enables a piece of trusted code to temporarily + enable access to more resources than are available directly to the code + that called it. Be very careful in your use of the privileged construct, + and always remember to make the privileged code section as small as possible. + patterns: + - pattern-inside: | + import java.security.*; + ... + - pattern-either: + - pattern: AccessController.doPrivileged(...); + - pattern: class $ACTION implements PrivilegedAction { ... } +- id: java.lang.security.httpservlet-path-traversal.httpservlet-path-traversal + metadata: + cwe: + - "CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')" + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + source-rule-url: https://find-sec-bugs.github.io/bugs.htm#PATH_TRAVERSAL_IN + references: + - https://www.owasp.org/index.php/Path_Traversal + category: security + technology: + - java + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: HIGH + impact: MEDIUM + confidence: MEDIUM + message: >- + Detected a potential path traversal. A malicious actor + could control the location of this file, to include going backwards + in the directory with '../'. To address this, ensure that user-controlled + variables in file paths are sanitized. You may also consider using a utility + method such as org.apache.commons.io.FilenameUtils.getName(...) to only + retrieve the file name from the path. + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - pattern: | + (HttpServletRequest $REQ) + - patterns: # this pattern is a hack to get the rule to recognize `map` as tainted source when `map = cookie.getValue(user_input)` is used. + - pattern-inside: | + (javax.servlet.http.Cookie[] $COOKIES) = (HttpServletRequest $REQ).getCookies(...); + ... + for (javax.servlet.http.Cookie $COOKIE: $COOKIES) { + ... + } + - pattern: | + $COOKIE.getValue(...) + - patterns: # use this pattern to catch cases where tainted array values are assigned to a variable (not caught by taint) + - pattern-inside: | + $TYPE[] $VALS = (HttpServletRequest $REQ).$GETFUNC(...); + ... + - pattern: | + $PARAM = $VALS[$INDEX]; + pattern-sanitizers: + - pattern: org.apache.commons.io.FilenameUtils.getName(...) + pattern-sinks: + - patterns: + - pattern-either: + - pattern: | + (java.io.File $FILE) = ... + - pattern: | + (java.io.FileOutputStream $FOS) = ... + - pattern: | + new java.io.FileInputStream(...) + severity: ERROR + languages: + - java +- id: java.lang.security.insecure-jms-deserialization.insecure-jms-deserialization + severity: WARNING + languages: + - java + metadata: + cwe: + - 'CWE-502: Deserialization of Untrusted Data' + owasp: + - A08:2017 - Insecure Deserialization + - A08:2021 - Software and Data Integrity Failures + asvs: + section: V5 Validation, Sanitization and Encoding + control_id: 5.5.3 Insecue Deserialization + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x13-V5-Validation-Sanitization-Encoding.md#v55-deserialization-prevention + version: '4' + references: + - https://www.blackhat.com/docs/us-16/materials/us-16-Kaiser-Pwning-Your-Java-Messaging-With-Deserialization-Vulnerabilities-wp.pdf + category: security + technology: + - java + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: LOW + impact: MEDIUM + confidence: MEDIUM + message: >- + JMS Object messages depend on Java Serialization for marshalling/unmarshalling + of the message payload when ObjectMessage.getObject() is called. + Deserialization of untrusted data can lead to security flaws; a remote attacker + could via a crafted JMS ObjectMessage to execute + arbitrary code with the permissions of the application listening/consuming JMS + Messages. + In this case, the JMS MessageListener consume an ObjectMessage type received inside + the onMessage method, which may lead to arbitrary code execution when calling + the $Y.getObject method. + patterns: + - pattern-inside: | + public class $JMS_LISTENER implements MessageListener { + ... + public void onMessage(Message $JMS_MSG) { + ... + } + } + - pattern-either: + - pattern-inside: $X = $Y.getObject(...); + - pattern-inside: $X = ($Z) $Y.getObject(...); +- id: java.lang.security.jackson-unsafe-deserialization.jackson-unsafe-deserialization + patterns: + - pattern-either: + - patterns: + - pattern-inside: | + ObjectMapper $OM = new ObjectMapper(...); + ... + - pattern-inside: | + $OM.enableDefaultTyping(); + ... + - pattern: $OM.readValue($JSON, ...); + - patterns: + - pattern-inside: | + class $CLASS { + ... + @JsonTypeInfo(use = Id.CLASS,...) + $TYPE $VAR; + ... + } + - metavariable-regex: + metavariable: $TYPE + regex: (Object|Serializable|Comparable) + - pattern: $OM.readValue($JSON, $CLASS.class); + - patterns: + - pattern-inside: | + class $CLASS { + ... + ObjectMapper $OM; + ... + $INITMETHODTYPE $INITMETHOD(...) { + ... + $OM = new ObjectMapper(); + ... + $OM.enableDefaultTyping(); + ... + } + ... + } + - pattern-inside: | + $METHODTYPE $METHOD(...) { + ... + } + - pattern: $OM.readValue($JSON, ...); + message: >- + When using Jackson to marshall/unmarshall JSON to Java objects, + enabling default typing is dangerous and can lead to RCE. If an attacker + can control `$JSON` it might be possible to provide a malicious JSON which + can be used to exploit unsecure deserialization. In order to prevent this + issue, avoid to enable default typing (globally or by using "Per-class" + annotations) and avoid using `Object` and other dangerous types for member + variable declaration which creating classes for Jackson based + deserialization. + languages: + - java + severity: WARNING + metadata: + category: security + subcategory: + - audit + cwe: + - "CWE-502: Deserialization of Untrusted Data" + confidence: MEDIUM + likelihood: LOW + impact: HIGH + owasp: + - A8:2017 Insecure Deserialization + - A8:2021 Software and Data Integrity Failures + references: + - https://swapneildash.medium.com/understanding-insecure-implementation-of-jackson-deserialization-7b3d409d2038 + - https://cowtowncoder.medium.com/on-jackson-cves-dont-panic-here-is-what-you-need-to-know-54cd0d6e8062 + - https://adamcaudill.com/2017/10/04/exploiting-jackson-rce-cve-2017-7525/ + technology: + - jackson +- id: java.lang.security.servletresponse-writer-xss.servletresponse-writer-xss + message: >- + Cross-site scripting detected in HttpServletResponse writer with variable '$VAR'. + User + input was detected going directly from the HttpServletRequest into output. Ensure + your + data is properly encoded using org.owasp.encoder.Encode.forHtml: 'Encode.forHtml($VAR)'. + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + source-rule-url: https://find-sec-bugs.github.io/bugs.htm#XSS_SERVLET + category: security + technology: + - java + references: + - https://owasp.org/Top10/A03_2021-Injection + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + severity: ERROR + patterns: + - pattern-inside: $TYPE $FUNC(..., HttpServletResponse $RESP, ...) { ... } + - pattern-inside: $VAR = $REQ.getParameter(...); ... + - pattern-either: + - pattern: $RESP.getWriter(...).write(..., $VAR, ...); + - pattern: | + $WRITER = $RESP.getWriter(...); + ... + $WRITER.write(..., $VAR, ...); + languages: + - java +- id: java.lang.security.use-snakeyaml-constructor.use-snakeyaml-constructor + languages: + - java + metadata: + owasp: + - A08:2017 - Insecure Deserialization + - A08:2021 - Software and Data Integrity Failures + cwe: + - 'CWE-502: Deserialization of Untrusted Data' + references: + - https://securitylab.github.com/research/swagger-yaml-parser-vulnerability/#snakeyaml-deserialization-vulnerability + category: security + technology: + - snakeyaml + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH + confidence: LOW + message: >- + Used SnakeYAML org.yaml.snakeyaml.Yaml() constructor with no arguments, which + is vulnerable to deserialization attacks. + Use the one-argument Yaml(...) constructor instead, with SafeConstructor or a + custom Constructor as the argument. + patterns: + - pattern: | + $Y = new org.yaml.snakeyaml.Yaml(); + ... + $Y.load(...); + severity: WARNING +- id: java.lang.security.xmlinputfactory-external-entities-enabled.xmlinputfactory-external-entities-enabled + severity: ERROR + metadata: + cwe: + - 'CWE-611: Improper Restriction of XML External Entity Reference' + owasp: + - A04:2017 - XML External Entities (XXE) + - A05:2021 - Security Misconfiguration + asvs: + section: V5 Validation, Sanitization and Encoding + control_id: 5.5.2 Insecue XML Deserialization + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x13-V5-Validation-Sanitization-Encoding.md#v55-deserialization-prevention + version: '4' + references: + - https://semgrep.dev/blog/2022/xml-security-in-java + - https://semgrep.dev/docs/cheat-sheets/java-xxe/ + - https://www.blackhat.com/docs/us-15/materials/us-15-Wang-FileCry-The-New-Age-Of-XXE-java-wp.pdf + category: security + technology: + - java + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH + confidence: LOW + message: >- + XML external entities are enabled for this XMLInputFactory. This is vulnerable + to XML external entity + attacks. Disable external entities by setting "javax.xml.stream.isSupportingExternalEntities" + to false. + patterns: + - pattern-either: + - pattern: (javax.xml.stream.XMLInputFactory $XMLFACTORY).setProperty("javax.xml.stream.isSupportingExternalEntities", true); + - pattern: (javax.xml.stream.XMLInputFactory $XMLFACTORY).setProperty(javax.xml.stream.XMLInputFactory.SUPPORT_DTD, true); + - pattern: (javax.xml.stream.XMLInputFactory $XMLFACTORY).setProperty("javax.xml.stream.isSupportingExternalEntities", Boolean.TRUE); + - pattern: (javax.xml.stream.XMLInputFactory $XMLFACTORY).setProperty(javax.xml.stream.XMLInputFactory.SUPPORT_DTD, Boolean.TRUE); + languages: + - java +- id: java.lang.security.xmlinputfactory-possible-xxe.xmlinputfactory-possible-xxe + severity: WARNING + metadata: + cwe: + - 'CWE-611: Improper Restriction of XML External Entity Reference' + owasp: + - A04:2017 - XML External Entities (XXE) + - A05:2021 - Security Misconfiguration + asvs: + section: V5 Validation, Sanitization and Encoding + control_id: 5.5.2 Insecue XML Deserialization + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x13-V5-Validation-Sanitization-Encoding.md#v55-deserialization-prevention + version: '4' + references: + - https://semgrep.dev/blog/2022/xml-security-in-java + - https://semgrep.dev/docs/cheat-sheets/java-xxe/ + - https://www.blackhat.com/docs/us-15/materials/us-15-Wang-FileCry-The-New-Age-Of-XXE-java-wp.pdf + - https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#xmlinputfactory-a-stax-parser + category: security + technology: + - java + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: LOW + impact: HIGH + confidence: MEDIUM + message: >- + XML external entities are not explicitly disabled for this XMLInputFactory. This + could be vulnerable to XML external entity + vulnerabilities. Explicitly disable external entities by setting "javax.xml.stream.isSupportingExternalEntities" + to false. + patterns: + - pattern-not-inside: | + $METHOD(...) { + ... + $XMLFACTORY.setProperty("javax.xml.stream.isSupportingExternalEntities", false); + ... + } + - pattern-not-inside: | + $METHOD(...) { + ... + $XMLFACTORY.setProperty(javax.xml.stream.XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, false); + ... + } + - pattern-not-inside: | + $METHOD(...) { + ... + $XMLFACTORY.setProperty("javax.xml.stream.isSupportingExternalEntities", Boolean.FALSE); + ... + } + - pattern-not-inside: | + $METHOD(...) { + ... + $XMLFACTORY.setProperty(javax.xml.stream.XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, Boolean.FALSE); + ... + } + - pattern-either: + - pattern: javax.xml.stream.XMLInputFactory.newFactory(...) + - pattern: new XMLInputFactory(...) + languages: + - java +- id: java.mongodb.security.injection.audit.mongodb-nosqli.mongodb-nosqli + message: >- + Detected non-constant data passed into a NoSQL query using the 'where' + evaluation operator. If this data can be controlled by an external user, this + is a NoSQL injection. Ensure data passed to the NoSQL query is not user controllable, + or properly sanitize the data. Ideally, avoid using the 'where' operator at all + and instead use the helper methods provided by com.mongodb.client.model.Filters + with comparative operators such as eq, ne, lt, gt, etc. + languages: + - java + severity: WARNING + patterns: + - pattern-either: + - pattern: (com.mongodb.BasicDBObject $QUERY).put("$where", $INPUT); + - pattern: | + (HashMap $MAP).put("$where", $INPUT); + ... + (com.mongodb.BasicDBObject $QUERY).putAll($MAP); + - pattern: (com.mongodb.BasicDBObject $QUERY).append("$where", $INPUT); + - pattern: new com.mongodb.BasicDBObject("$where", $INPUT); + - pattern: | + (HashMap $MAP).put("$where", $INPUT); + ... + new com.mongodb.BasicDBObject($MAP); + - pattern: | + (HashMap $MAP).put("$where", $INPUT); + ... + String json = new JSONObject($MAP).toString(); + ... + (com.mongodb.BasicDBObject $QUERY).parse((String $JSON)); + - pattern: com.mongodb.BasicDBObjectBuilder.start().add("$where", $INPUT); + - pattern: com.mongodb.BasicDBObjectBuilder.start().append("$where", $INPUT); + - pattern: com.mongodb.BasicDBObjectBuilder.start("$where", $INPUT); + - pattern: | + (HashMap $MAP).put("$where", $INPUT); + ... + com.mongodb.BasicDBObjectBuilder.start($MAP); + - metavariable-pattern: + metavariable: $INPUT + patterns: + - pattern: | + ... + - pattern-not: | + "..." + metadata: + category: security + technology: + - nosql + - mongodb + cwe: + - 'CWE-943: Improper Neutralization of Special Elements in Data Query Logic' + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + asvs: + section: 'V5: Validation, Sanitization and Encoding Verification Requirements' + control_id: 5.3.4 Injection Prevention + control_url: https://github.com/OWASP/ASVS/blob/master/5.0/en/0x13-V5-Validation-Sanitization-Encoding.md#v53-output-encoding-and-injection-prevention + version: '5' + references: + - https://owasp.org/Top10/A03_2021-Injection + - https://www.mongodb.com/docs/manual/tutorial/query-documents/ + - https://www.mongodb.com/docs/manual/reference/operator/query/where/ + subcategory: + - audit + likelihood: LOW + impact: HIGH + confidence: LOW +- id: java.rmi.security.server-dangerous-class-deserialization.server-dangerous-class-deserialization + severity: WARNING + languages: + - java + metadata: + cwe: + - 'CWE-502: Deserialization of Untrusted Data' + owasp: + - A08:2017 - Insecure Deserialization + - A08:2021 - Software and Data Integrity Failures + references: + - https://mogwailabs.de/blog/2019/03/attacking-java-rmi-services-after-jep-290/ + category: security + technology: + - rmi + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH + confidence: LOW + message: >- + Using a non-primitive class with Java RMI may be an insecure deserialization vulnerability. Depending + on the underlying implementation. This object could be manipulated by a malicious actor allowing them + to + execute code on your system. Instead, use an integer ID to look up your object, or consider alternative + serialization schemes such as JSON. + patterns: + - pattern: | + interface $INTERFACE extends Remote { + $RETURNTYPE $METHOD($CLASS $PARAM) throws RemoteException; + } + - metavariable-regex: + metavariable: $CLASS + regex: (?!int|boolean|short|long|byte|char|float|double) +- id: java.rmi.security.server-dangerous-object-deserialization.server-dangerous-object-deserialization + severity: ERROR + metadata: + cwe: + - 'CWE-502: Deserialization of Untrusted Data' + owasp: + - A08:2017 - Insecure Deserialization + - A08:2021 - Software and Data Integrity Failures + references: + - https://frohoff.github.io/appseccali-marshalling-pickles/ + - https://book.hacktricks.xyz/network-services-pentesting/1099-pentesting-java-rmi + - https://youtu.be/t_aw1mDNhzI + - https://github.com/qtc-de/remote-method-guesser + - https://github.com/openjdk/jdk/blob/master/src/java.rmi/share/classes/sun/rmi/server/UnicastRef.java#L303C4-L331 + category: security + technology: + - rmi + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH + confidence: LOW + message: >- + Using an arbitrary object ('$PARAMTYPE $PARAM') with Java RMI is an insecure deserialization + vulnerability. This object can be manipulated by a malicious actor allowing them to execute + code on your system. Instead, use an integer ID to look up your object, or consider alternative + serialization schemes such as JSON. + languages: + - java + patterns: + - pattern: | + interface $INTERFACE extends Remote { + $RETURNTYPE $METHOD($PARAMTYPE $PARAM) throws RemoteException; + } + - metavariable-pattern: + metavariable: $PARAMTYPE + # Needed because we unfortunately cannot parse primitive types as + # standalone patterns in Java + language: generic + patterns: + # Not actually a primitive but handled specially in deserialization + # code, so not vulnerable. + - pattern-not: String + - pattern-not: java.lang.String + - pattern-not: boolean + - pattern-not: Boolean + - pattern-not: java.lang.Boolean + - pattern-not: byte + - pattern-not: Byte + - pattern-not: java.lang.Byte + - pattern-not: char + - pattern-not: Character + - pattern-not: java.lang.Character + - pattern-not: double + - pattern-not: Double + - pattern-not: java.lang.Double + - pattern-not: float + - pattern-not: Float + - pattern-not: java.lang.Float + - pattern-not: int + - pattern-not: Integer + - pattern-not: java.lang.Integer + - pattern-not: long + - pattern-not: Long + - pattern-not: java.lang.Long + - pattern-not: short + - pattern-not: Short + - pattern-not: java.lang.Short +- id: java.servlets.security.cookie-issecure-false.cookie-issecure-false + patterns: + - pattern: $COOKIE = new Cookie($...ARGS); + - pattern-not-inside: | + $COOKIE = new Cookie(...); + ... + $COOKIE.setSecure(...); + message: "Default session middleware settings: `setSecure` not set to true. This + ensures that the cookie is sent only over HTTPS to prevent cross-site + scripting attacks." + fix: | + $COOKIE = new Cookie($...ARGS); + $COOKIE.setSecure(true); + metadata: + vulnerability: Insecure Transport + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + cwe: + - "CWE-319: Cleartext Transmission of Sensitive Information" + references: + - https://docs.oracle.com/javaee/6/api/javax/servlet/http/Cookie.html#setSecure(boolean) + - https://owasp.org/www-community/controls/SecureCookieAttribute + category: security + technology: + - java + - cookie + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: + - java + severity: WARNING +- id: java.servlets.security.cookie-setsecure.cookie-setsecure + patterns: + - patterns: + - pattern-inside: | + $COOKIE = new Cookie(...); + ... + - pattern: | + $COOKIE.setSecure(false); + - pattern-not-inside: | + $COOKIE = new Cookie(...); + ... + $COOKIE.setSecure(true); + message: "Default session middleware settings: `setSecure` not set to true. This + ensures that the cookie is sent only over HTTPS to prevent cross-site + scripting attacks." + fix-regex: + regex: setSecure\(false\) + replacement: setSecure(true) + metadata: + vulnerability: Insecure Transport + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + cwe: + - "CWE-319: Cleartext Transmission of Sensitive Information" + references: + - https://docs.oracle.com/javaee/6/api/javax/servlet/http/Cookie.html#setSecure(boolean) + - https://owasp.org/www-community/controls/SecureCookieAttribute + category: security + technology: + - java + - cookie + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: + - java + severity: WARNING +- id: java.spring.security.audit.spel-injection.spel-injection + message: >- + A Spring expression is built with a dynamic value. The source of the value(s) should be verified to + avoid that unfiltered values fall into this risky code evaluation. + metadata: + cwe: + - "CWE-94: Improper Control of Generation of Code ('Code Injection')" + owasp: + - A03:2021 - Injection + source-rule-url: https://find-sec-bugs.github.io/bugs.htm#SPEL_INJECTION + category: security + technology: + - spring + references: + - https://owasp.org/Top10/A03_2021-Injection + cwe2022-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH + confidence: LOW + severity: WARNING + languages: [java] + patterns: + - pattern-either: + - pattern-inside: | + class $CLASS { + ... + ExpressionParser $PARSER; + ... + } + - pattern-inside: | + class $CLASS { + ... + ExpressionParser $PARSER = ...; + ... + } + - pattern-inside: | + $X $METHOD(...) { + ... + ExpressionParser $PARSER = ...; + ... + } + - pattern-inside: | + class $CLASS { + ... + SpelExpressionParser $PARSER; + ... + } + - pattern-inside: | + class $CLASS { + ... + SpelExpressionParser $PARSER = ...; + ... + } + - pattern-inside: | + $X $METHOD(...) { + ... + SpelExpressionParser $PARSER = ...; + ... + } + - pattern-inside: | + class $CLASS { + ... + TemplateAwareExpressionParser $PARSER; + ... + } + - pattern-inside: | + class $CLASS { + ... + TemplateAwareExpressionParser $PARSER = ...; + ... + } + - pattern-inside: | + $X $METHOD(...) { + ... + TemplateAwareExpressionParser $PARSER = ...; + ... + } + - pattern: | + $X $METHOD(...) { + ... + $PARSER.parseExpression(...); + ... + } + - pattern-not: | + $X $METHOD(...) { + ... + $PARSER.parseExpression("..."); + ... + } + - pattern-not: | + $X $METHOD(...) { + ... + String $S = "..."; + ... + $PARSER.parseExpression($S); + ... + } +- id: java.spring.security.audit.spring-actuator-fully-enabled-yaml.spring-actuator-fully-enabled-yaml + patterns: + - pattern-inside: | + management: + ... + endpoints: + ... + web: + ... + exposure: + ... + - pattern: | + include: "*" + message: >- + Spring Boot Actuator is fully enabled. This exposes sensitive endpoints such as /actuator/env, /actuator/logfile, + /actuator/heapdump and others. + Unless you have Spring Security enabled or another means to protect these endpoints, this functionality + is available without authentication, causing a severe security risk. + severity: WARNING + languages: [yaml] + metadata: + cwe: + - 'CWE-200: Exposure of Sensitive Information to an Unauthorized Actor' + owasp: + - A01:2021 - Broken Access Control + references: + - https://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-features.html#production-ready-endpoints-exposing-endpoints + - https://medium.com/walmartglobaltech/perils-of-spring-boot-actuators-misconfiguration-185c43a0f785 + - https://blog.maass.xyz/spring-actuator-security-part-1-stealing-secrets-using-spring-actuators + category: security + technology: + - spring + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: HIGH + confidence: MEDIUM +- id: java.spring.security.audit.spring-actuator-fully-enabled.spring-actuator-fully-enabled + pattern: management.endpoints.web.exposure.include=* + message: >- + Spring Boot Actuator is fully enabled. This exposes sensitive endpoints such as /actuator/env, /actuator/logfile, + /actuator/heapdump and others. + Unless you have Spring Security enabled or another means to protect these endpoints, this functionality + is available without authentication, causing a significant security risk. + severity: ERROR + languages: [generic] + paths: + include: + - '*properties' + metadata: + cwe: + - 'CWE-200: Exposure of Sensitive Information to an Unauthorized Actor' + owasp: + - A01:2021 - Broken Access Control + references: + - https://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-features.html#production-ready-endpoints-exposing-endpoints + - https://medium.com/walmartglobaltech/perils-of-spring-boot-actuators-misconfiguration-185c43a0f785 + - https://blog.maass.xyz/spring-actuator-security-part-1-stealing-secrets-using-spring-actuators + category: security + technology: + - spring + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: HIGH + confidence: MEDIUM +- id: java.spring.security.audit.spring-actuator-non-health-enabled-yaml.spring-actuator-dangerous-endpoints-enabled-yaml + patterns: + - pattern-inside: | + management: + ... + endpoints: + ... + web: + ... + exposure: + ... + include: + ... + - pattern: | + include: [..., $ACTUATOR, ...] + - metavariable-comparison: + metavariable: $ACTUATOR + comparison: not str($ACTUATOR) in ["health","*"] + message: Spring Boot Actuator "$ACTUATOR" is enabled. Depending on the actuator, this can pose a significant + security risk. Please double-check if the actuator is needed and properly secured. + severity: WARNING + languages: + - yaml + metadata: + cwe: + - 'CWE-200: Exposure of Sensitive Information to an Unauthorized Actor' + owasp: + - A01:2021 - Broken Access Control + references: + - https://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-features.html#production-ready-endpoints-exposing-endpoints + - https://medium.com/walmartglobaltech/perils-of-spring-boot-actuators-misconfiguration-185c43a0f785 + - https://blog.maass.xyz/spring-actuator-security-part-1-stealing-secrets-using-spring-actuators + category: security + technology: + - spring + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: HIGH + confidence: MEDIUM +- id: java.spring.security.audit.spring-actuator-non-health-enabled.spring-actuator-dangerous-endpoints-enabled + patterns: + - pattern: management.endpoints.web.exposure.include=$...ACTUATORS + - metavariable-comparison: + metavariable: $...ACTUATORS + comparison: not str($...ACTUATORS) in ["health","*"] + message: Spring Boot Actuators "$...ACTUATORS" are enabled. Depending on the actuators, this can pose + a significant security risk. Please double-check if the actuators are needed and properly secured. + severity: WARNING + languages: + - generic + options: + # Limit matches to a single line to work with a limitation of the generic parser + generic_ellipsis_max_span: 0 + metadata: + cwe: + - 'CWE-200: Exposure of Sensitive Information to an Unauthorized Actor' + owasp: + - A01:2021 - Broken Access Control + references: + - https://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-features.html#production-ready-endpoints-exposing-endpoints + - https://medium.com/walmartglobaltech/perils-of-spring-boot-actuators-misconfiguration-185c43a0f785 + - https://blog.maass.xyz/spring-actuator-security-part-1-stealing-secrets-using-spring-actuators + category: security + technology: + - spring + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: HIGH + confidence: MEDIUM +- id: java.spring.security.audit.spring-csrf-disabled.spring-csrf-disabled + message: >- + CSRF protection is disabled for this configuration. This is a security risk. + metadata: + cwe: + - 'CWE-352: Cross-Site Request Forgery (CSRF)' + owasp: + - A01:2021 - Broken Access Control + source-rule-url: https://find-sec-bugs.github.io/bugs.htm#SPRING_CSRF_PROTECTION_DISABLED + asvs: + section: V4 Access Control + control_id: 4.2.2 CSRF + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x12-V4-Access-Control.md#v42-operation-level-access-control + version: '4' + category: security + technology: + - spring + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + severity: WARNING + languages: [java] + pattern: $OBJ.csrf(...).disable(...) +- id: java.spring.security.audit.spring-jsp-eval.spring-jsp-eval + pattern: | + + message: >- + A Spring expression is built with a dynamic value. The source of the value(s) should be verified to + avoid that unfiltered values fall into this risky code evaluation. + severity: WARNING + languages: [generic] + metadata: + cwe: + - "CWE-95: Improper Neutralization of Directives in Dynamically Evaluated Code ('Eval Injection')" + owasp: + - A03:2021 - Injection + source-rule-url: https://find-sec-bugs.github.io/bugs.htm#JSP_SPRING_EVAL + category: security + technology: + - spring + references: + - https://owasp.org/Top10/A03_2021-Injection + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + paths: + include: + - '*.jsp' +- id: java.spring.security.audit.spring-sqli.spring-sqli + mode: taint + pattern-sources: + - patterns: + - pattern: $ARG + - pattern-inside: | + public $T $M (..., String $ARG,...){...} + pattern-sanitizers: + - not_conflicting: true + pattern-either: + - patterns: + - focus-metavariable: $A + - pattern-inside: | + new $TYPE(...,$A,...); + pattern-sinks: + - patterns: + - pattern-either: + - patterns: + - focus-metavariable: $A + - pattern: | + new PreparedStatementCreatorFactory($A,...); + - patterns: + - focus-metavariable: $A + - pattern: | + (JdbcTemplate $T).$M($A,...) + - patterns: + - pattern: (String $A) + - pattern-inside: | + (JdbcTemplate $T).batchUpdate(...) + - patterns: + - focus-metavariable: $A + - pattern: | + NamedParameterBatchUpdateUtils.$M($A,...) + - patterns: + - focus-metavariable: $A + - pattern: | + BatchUpdateUtils.$M($A,...) + message: >- + Detected a string argument from a public method contract in a raw SQL statement. This could lead to + SQL + injection if variables in the SQL statement are not properly sanitized. + Use a prepared statements (java.sql.PreparedStatement) instead. You + can obtain a PreparedStatement using 'connection.prepareStatement'. + languages: [java] + severity: WARNING + options: + taint_assume_safe_numbers: true + taint_assume_safe_booleans: true + metadata: + cwe: + - "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')" + category: security + technology: + - spring + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + references: + - https://owasp.org/Top10/A03_2021-Injection + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM +- id: java.spring.security.audit.spring-unvalidated-redirect.spring-unvalidated-redirect + message: >- + Application redirects a user to a destination URL specified by a user supplied parameter that is not + validated. + metadata: + cwe: + - "CWE-601: URL Redirection to Untrusted Site ('Open Redirect')" + owasp: + - A01:2021 - Broken Access Control + source-rule-url: https://find-sec-bugs.github.io/bugs.htm#UNVALIDATED_REDIRECT + category: security + technology: + - spring + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + severity: WARNING + languages: [java] + pattern-either: + - pattern: | + $X $METHOD(...,String $URL,...) { + return "redirect:" + $URL; + } + - pattern: | + $X $METHOD(...,String $URL,...) { + ... + String $REDIR = "redirect:" + $URL; + ... + return $REDIR; + ... + } + - pattern: | + $X $METHOD(...,String $URL,...) { + ... + new ModelAndView("redirect:" + $URL); + ... + } + - pattern: |- + $X $METHOD(...,String $URL,...) { + ... + String $REDIR = "redirect:" + $URL; + ... + new ModelAndView($REDIR); + ... + } +- id: java.spring.security.injection.tainted-file-path.tainted-file-path + languages: + - java + severity: ERROR + message: >- + Detected user input controlling a file path. An attacker could control the location of this + file, to include going backwards in the directory with '../'. To address this, ensure that user-controlled + variables in file paths are sanitized. You may also consider using a utility method such as org.apache.commons.io.FilenameUtils.getName(...) + to only retrieve the file name from the path. + options: + interfile: true + metadata: + cwe: + - 'CWE-23: Relative Path Traversal' + owasp: + - A01:2021 - Broken Access Control + references: + - https://owasp.org/www-community/attacks/Path_Traversal + category: security + technology: + - java + - spring + subcategory: + - vuln + impact: HIGH + likelihood: MEDIUM + confidence: HIGH + interfile: true + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - pattern-inside: | + $METHODNAME(..., @$REQ(...) $TYPE $SOURCE,...) { + ... + } + - pattern-inside: | + $METHODNAME(..., @$REQ $TYPE $SOURCE,...) { + ... + } + - metavariable-regex: + metavariable: $TYPE + regex: ^(?!(Integer|Long|Float|Double|Char|Boolean|int|long|float|double|char|boolean)) + - metavariable-regex: + metavariable: $REQ + regex: (RequestBody|PathVariable|RequestParam|RequestHeader|CookieValue|ModelAttribute) + - focus-metavariable: $SOURCE + pattern-sinks: + - patterns: + - pattern-either: + - pattern: new File(...) + - pattern: new java.io.File(...) + - pattern: new FileReader(...) + - pattern: new java.io.FileReader(...) + - pattern: new FileInputStream(...) + - pattern: new java.io.FileInputStream(...) + - pattern: (Paths $PATHS).get(...) + - patterns: + - pattern: | + $CLASS.$FUNC(...) + - metavariable-regex: + metavariable: $FUNC + regex: ^(getResourceAsStream|getResource)$ + - patterns: + - pattern-either: + - pattern: new ClassPathResource($FILE, ...) + - pattern: ResourceUtils.getFile($FILE, ...) + - pattern: new FileOutputStream($FILE, ...) + - pattern: new java.io.FileOutputStream($FILE, ...) + - pattern: new StreamSource($FILE, ...) + - pattern: new javax.xml.transform.StreamSource($FILE, ...) + - pattern: FileUtils.openOutputStream($FILE, ...) + - focus-metavariable: $FILE + pattern-sanitizers: + - pattern: org.apache.commons.io.FilenameUtils.getName(...) +- id: java.spring.security.injection.tainted-html-string.tainted-html-string + languages: + - java + severity: ERROR + message: >- + Detected user input flowing into a manually constructed HTML string. + You may be accidentally bypassing secure methods of rendering HTML by + manually constructing HTML and this could create a cross-site scripting + vulnerability, which could let attackers steal sensitive user data. To be + sure this is safe, check that the HTML is rendered safely. You can use + the OWASP ESAPI encoder if you must render user data. + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html + category: security + technology: + - java + - spring + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: HIGH + impact: MEDIUM + confidence: MEDIUM + mode: taint + pattern-sources: + - label: INPUT + patterns: + - pattern-either: + - pattern-inside: | + $METHODNAME(..., @$REQ(...) $TYPE $SOURCE,...) { + ... + } + - pattern-inside: | + $METHODNAME(..., @$REQ $TYPE $SOURCE,...) { + ... + } + - metavariable-regex: + metavariable: $TYPE + regex: ^(?!(Integer|Long|Float|Double|Char|Boolean|int|long|float|double|char|boolean)) + - metavariable-regex: + metavariable: $REQ + regex: (RequestBody|PathVariable|RequestParam|RequestHeader|CookieValue|ModelAttribute) + - focus-metavariable: $SOURCE + - label: CONCAT + by-side-effect: true + requires: INPUT + patterns: + - pattern-either: + - pattern: | + "$HTMLSTR" + ... + - pattern: | + "$HTMLSTR".concat(...) + - patterns: + - pattern-inside: | + StringBuilder $SB = new StringBuilder("$HTMLSTR"); + ... + - pattern: $SB.append(...) + - patterns: + - pattern-inside: | + $VAR = "$HTMLSTR"; + ... + - pattern: $VAR += ... + - pattern: String.format("$HTMLSTR", ...) + - patterns: + - pattern-inside: | + String $VAR = "$HTMLSTR"; + ... + - pattern: String.format($VAR, ...) + - metavariable-regex: + metavariable: $HTMLSTR + regex: ^<\w+ + pattern-propagators: + - pattern: (StringBuilder $SB).append($...TAINTED) + from: $...TAINTED + to: $SB + - pattern: $VAR += $...TAINTED + from: $...TAINTED + to: $VAR + pattern-sinks: + - requires: CONCAT + patterns: + - pattern-either: + - pattern: new ResponseEntity<>($PAYLOAD, ...) + - pattern: new ResponseEntity<$ERROR>($PAYLOAD, ...) + - pattern: ResponseEntity. ... .body($PAYLOAD) + - patterns: + - pattern: | + ResponseEntity.$RESPFUNC($PAYLOAD). ... + - metavariable-regex: + metavariable: $RESPFUNC + regex: ^(ok|of)$ + - focus-metavariable: $PAYLOAD + pattern-sanitizers: + - pattern-either: + - pattern: Encode.forHtml(...) + - pattern: (PolicyFactory $POLICY).sanitize(...) + - pattern: (AntiSamy $AS).scan(...) + - pattern: JSoup.clean(...) +- id: java.spring.security.injection.tainted-sql-string.tainted-sql-string + languages: + - java + severity: ERROR + message: User data flows into this manually-constructed SQL string. User data + can be safely inserted into SQL strings using prepared statements or an + object-relational mapper (ORM). Manually-constructed SQL strings is a + possible indicator of SQL injection, which could let an attacker steal or + manipulate data from the database. Instead, use prepared statements + (`connection.PreparedStatement`) or a safe library. + metadata: + cwe: + - "CWE-89: Improper Neutralization of Special Elements used in an SQL + Command ('SQL Injection')" + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + references: + - https://docs.oracle.com/javase/7/docs/api/java/sql/PreparedStatement.html + category: security + technology: + - spring + license: Commons Clause License Condition v1.0[LGPL-2.1-only] + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: HIGH + impact: MEDIUM + confidence: MEDIUM + interfile: true + options: + taint_assume_safe_numbers: true + taint_assume_safe_booleans: true + interfile: true + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - pattern-inside: | + $METHODNAME(..., @$REQ(...) $TYPE $SOURCE,...) { + ... + } + - pattern-inside: | + $METHODNAME(..., @$REQ $TYPE $SOURCE,...) { + ... + } + - metavariable-regex: + metavariable: $REQ + regex: (RequestBody|PathVariable|RequestParam|RequestHeader|CookieValue) + - metavariable-regex: + metavariable: $TYPE + regex: ^(?!(Integer|Long|Float|Double|Char|Boolean|int|long|float|double|char|boolean)) + - focus-metavariable: $SOURCE + pattern-sinks: + - patterns: + - pattern-either: + - pattern: | + "$SQLSTR" + ... + - pattern: | + "$SQLSTR".concat(...) + - patterns: + - pattern-inside: | + StringBuilder $SB = new StringBuilder("$SQLSTR"); + ... + - pattern: $SB.append(...) + - patterns: + - pattern-inside: | + $VAR = "$SQLSTR"; + ... + - pattern: $VAR += ... + - pattern: String.format("$SQLSTR", ...) + - patterns: + - pattern-inside: | + String $VAR = "$SQLSTR"; + ... + - pattern: String.format($VAR, ...) + - pattern-not-inside: System.out.println(...) + - pattern-not-inside: $LOG.info(...) + - pattern-not-inside: $LOG.warn(...) + - pattern-not-inside: $LOG.warning(...) + - pattern-not-inside: $LOG.debug(...) + - pattern-not-inside: $LOG.debugging(...) + - pattern-not-inside: $LOG.error(...) + - pattern-not-inside: new Exception(...) + - pattern-not-inside: throw ...; + - metavariable-regex: + metavariable: $SQLSTR + regex: (?i)(select|delete|insert|create|update|alter|drop)\b +- id: java.spring.security.injection.tainted-system-command.tainted-system-command + languages: + - java + severity: ERROR + mode: taint + pattern-propagators: + - pattern: (StringBuilder $STRB).append($INPUT) + from: $INPUT + to: $STRB + label: CONCAT + requires: INPUT + pattern-sources: + - patterns: + - pattern-either: + - pattern-inside: | + $METHODNAME(..., @$REQ(...) $TYPE $SOURCE,...) { + ... + } + - pattern-inside: | + $METHODNAME(..., @$REQ $TYPE $SOURCE,...) { + ... + } + - metavariable-regex: + metavariable: $TYPE + regex: ^(?!(Integer|Long|Float|Double|Char|Boolean|int|long|float|double|char|boolean)) + - metavariable-regex: + metavariable: $REQ + regex: (RequestBody|PathVariable|RequestParam|RequestHeader|CookieValue|ModelAttribute) + - focus-metavariable: $SOURCE + label: INPUT + - patterns: + - pattern-either: + - pattern: $X + $SOURCE + - pattern: $SOURCE + $Y + - pattern: String.format("...", ..., $SOURCE, ...) + - pattern: String.join("...", ..., $SOURCE, ...) + - pattern: (String $STR).concat($SOURCE) + - pattern: $SOURCE.concat(...) + - pattern: $X += $SOURCE + - pattern: $SOURCE += $X + label: CONCAT + requires: INPUT + pattern-sinks: + - patterns: + - pattern-either: + - pattern: | + (Process $P) = new Process(...); + - pattern: | + (ProcessBuilder $PB).command(...); + - patterns: + - pattern-either: + - pattern: | + (Runtime $R).$EXEC(...); + - pattern: | + Runtime.getRuntime(...).$EXEC(...); + - metavariable-regex: + metavariable: $EXEC + regex: (exec|loadLibrary|load) + - patterns: + - pattern: | + (ProcessBuilder $PB).command(...).$ADD(...); + - metavariable-regex: + metavariable: $ADD + regex: (add|addAll) + - patterns: + - pattern-either: + - patterns: + - pattern-inside: | + $BUILDER = new ProcessBuilder(...); + ... + - pattern: $BUILDER.start(...) + - pattern: | + new ProcessBuilder(...). ... .start(...); + requires: CONCAT + message: >- + Detected user input entering a method which executes a system command. + This could result in a command injection vulnerability, which allows an + attacker to inject an arbitrary system command onto the server. The attacker + could download malware onto or steal data from the server. Instead, use + ProcessBuilder, separating the command into individual arguments, like this: + `new ProcessBuilder("ls", "-al", targetDirectory)`. Further, make sure you + hardcode or allowlist the actual command so that attackers can't run arbitrary commands. + metadata: + cwe: + - "CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')" + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + category: security + technology: + - java + - spring + confidence: HIGH + references: + - https://www.stackhawk.com/blog/command-injection-java/ + - https://cheatsheetseries.owasp.org/cheatsheets/OS_Command_Injection_Defense_Cheat_Sheet.html + - https://github.com/github/codeql/blob/main/java/ql/src/Security/CWE/CWE-078/ExecUnescaped.java + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: HIGH + impact: HIGH +- id: java.spring.security.injection.tainted-url-host.tainted-url-host + languages: + - java + severity: ERROR + message: >- + User data flows into the host portion of this manually-constructed URL. + This could allow an attacker to send data to their own server, + potentially exposing sensitive data such as cookies or authorization + information sent with this request. They could also probe internal + servers or other resources that the server running this code can access. + (This is called server-side request forgery, or SSRF.) Do not allow + arbitrary hosts. Instead, create an allowlist for approved hosts, hardcode + the correct host, or ensure that the user data can only affect the path or parameters. + options: + interfile: true + metadata: + cwe: + - 'CWE-918: Server-Side Request Forgery (SSRF)' + owasp: + - A10:2021 - Server-Side Request Forgery (SSRF) + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet.html + category: security + technology: + - java + - spring + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + impact: MEDIUM + likelihood: MEDIUM + confidence: MEDIUM + interfile: true + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - pattern-inside: | + $METHODNAME(..., @$REQ(...) $TYPE $SOURCE,...) { + ... + } + - pattern-inside: | + $METHODNAME(..., @$REQ $TYPE $SOURCE,...) { + ... + } + - metavariable-regex: + metavariable: $TYPE + regex: ^(?!(Integer|Long|Float|Double|Char|Boolean|int|long|float|double|char|boolean)) + - metavariable-regex: + metavariable: $REQ + regex: (RequestBody|PathVariable|RequestParam|RequestHeader|CookieValue|ModelAttribute) + - focus-metavariable: $SOURCE + pattern-sinks: + - pattern-either: + - pattern: new URL($ONEARG) + - patterns: + - pattern-either: + - pattern: | + "$URLSTR" + ... + - pattern: | + "$URLSTR".concat(...) + - patterns: + - pattern-inside: | + StringBuilder $SB = new StringBuilder("$URLSTR"); + ... + - pattern: $SB.append(...) + - patterns: + - pattern-inside: | + $VAR = "$URLSTR"; + ... + - pattern: $VAR += ... + - patterns: + - pattern: String.format("$URLSTR", ...) + - pattern-not: String.format("$URLSTR", "...", ...) + - patterns: + - pattern-inside: | + String $VAR = "$URLSTR"; + ... + - pattern: String.format($VAR, ...) + - metavariable-regex: + metavariable: $URLSTR + regex: http(s?)://%(v|s|q).* +- id: java.spring.security.unrestricted-request-mapping.unrestricted-request-mapping + patterns: + - pattern-inside: | + @RequestMapping(...) + $RETURNTYPE $METHOD(...) { ... } + - pattern-not-inside: | + @RequestMapping(..., method = $X, ...) + $RETURNTYPE $METHOD(...) { ... } + - pattern: | + RequestMapping + message: >- + Detected a method annotated with 'RequestMapping' that does not specify + the HTTP method. CSRF protections are not enabled for GET, HEAD, TRACE, + or OPTIONS, and by default all HTTP methods are allowed when the HTTP method + is not explicitly specified. This means that a method that performs state + changes could be vulnerable to CSRF attacks. To mitigate, add the 'method' + field and specify the HTTP method (such as 'RequestMethod.POST'). + severity: WARNING + metadata: + cwe: + - 'CWE-352: Cross-Site Request Forgery (CSRF)' + owasp: + - A01:2021 - Broken Access Control + source-rule-url: https://find-sec-bugs.github.io/bugs.htm#SPRING_CSRF_UNRESTRICTED_REQUEST_MAPPING + references: + - https://find-sec-bugs.github.io/bugs.htm#SPRING_CSRF_UNRESTRICTED_REQUEST_MAPPING + category: security + technology: + - spring + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + languages: [java] +- id: javascript.ajv.security.audit.ajv-allerrors-true.ajv-allerrors-true + message: >- + By setting `allErrors: true` in `Ajv` library, all error objects will be allocated without limit. + This allows the attacker to produce a huge number of errors which can lead to denial of service. Do + not use `allErrors: true` in production. + metadata: + cwe: + - 'CWE-400: Uncontrolled Resource Consumption' + category: security + technology: + - ajv + references: + - https://ajv.js.org/options.html#allerrors + cwe2022-top25: true + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: + - javascript + - typescript + severity: WARNING + pattern-either: + - pattern: | + new Ajv({...,allErrors: true,...},...) + - patterns: + - pattern: | + new Ajv($SETTINGS,...) + - pattern-inside: | + $SETTINGS = {...,allErrors: true,...} + ... +- id: javascript.angular.security.detect-angular-element-methods.detect-angular-element-methods + message: >- + Use of angular.element can lead to XSS if user-input is treated as part of the HTML element within + `$SINK`. It is recommended to contextually output encode user-input, before inserting into `$SINK`. If + the HTML needs to be preserved it is recommended to sanitize the input using $sce.getTrustedHTML or + $sanitize. + metadata: + confidence: LOW + references: + - https://docs.angularjs.org/api/ng/function/angular.element + - https://owasp.org/www-chapter-london/assets/slides/OWASPLondon20170727_AngularJS.pdf + category: security + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + technology: + - angularjs + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: LOW + impact: MEDIUM + languages: + - javascript + - typescript + severity: INFO + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - patterns: + - pattern-inside: | + function(..., $SCOPE, ...) { ... } + - focus-metavariable: $SCOPE + - metavariable-regex: + metavariable: $SCOPE + regex: ^\$scope$ + - pattern: $rootScope + - pattern: $injector.get('$rootScope') + - pattern: $injector.get('$scope') + pattern-sinks: + - patterns: + - pattern-either: + - pattern-inside: | + angular.element(...). ... .$SINK($QUERY) + - pattern-inside: | + $ANGULAR = angular.element(...) + ... + $ANGULAR. ... .$SINK($QUERY) + - metavariable-regex: + metavariable: $SINK + regex: ^(after|append|html|prepend|replaceWith|wrap)$ + - focus-metavariable: $QUERY + pattern-sanitizers: + - patterns: + - pattern-either: + - pattern: $sce.getTrustedHtml(...) + - pattern: $sanitize(...) + - pattern: DOMPurify.sanitize(...) +- id: javascript.angular.security.detect-angular-element-taint.detect-angular-element-taint + message: >- + Use of angular.element can lead to XSS if user-input is treated as part of the HTML element within + `$SINK`. It is recommended to contextually output encode user-input, before inserting into `$SINK`. If + the HTML needs to be preserved it is recommended to sanitize the input using $sce.getTrustedHTML or + $sanitize. + metadata: + confidence: MEDIUM + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + references: + - https://docs.angularjs.org/api/ng/function/angular.element + - https://owasp.org/www-chapter-london/assets/slides/OWASPLondon20170727_AngularJS.pdf + category: security + technology: + - angularjs + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: HIGH + impact: MEDIUM + languages: + - javascript + - typescript + severity: WARNING + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - pattern: window.location.search + - pattern: window.document.location.search + - pattern: document.location.search + - pattern: location.search + - pattern: $location.search(...) + - patterns: + - pattern-either: + - pattern: $DECODE(<... location.hash ...>) + - pattern: $DECODE(<... window.location.hash ...>) + - pattern: $DECODE(<... document.location.hash ...>) + - pattern: $DECODE(<... location.href ...>) + - pattern: $DECODE(<... window.location.href ...>) + - pattern: $DECODE(<... document.location.href ...>) + - pattern: $DECODE(<... document.URL ...>) + - pattern: $DECODE(<... window.document.URL ...>) + - pattern: $DECODE(<... document.location.href ...>) + - pattern: $DECODE(<... document.location.href ...>) + - pattern: $DECODE(<... $location.absUrl() ...>) + - pattern: $DECODE(<... $location.url() ...>) + - pattern: $DECODE(<... $location.hash() ...>) + - metavariable-regex: + metavariable: $DECODE + regex: ^(unescape|decodeURI|decodeURIComponent)$ + - patterns: + - pattern-inside: $http.$METHOD(...).$CONTINUE(function $FUNC($RES) {...}) + - metavariable-regex: + metavariable: $METHOD + regex: ^(get|delete|head|jsonp|post|put|patch) + - pattern: $RES.data + pattern-sinks: + - patterns: + - pattern-either: + - pattern-inside: | + angular.element(...). ... .$SINK($QUERY) + - pattern-inside: | + $ANGULAR = angular.element(...) + ... + $ANGULAR. ... .$SINK($QUERY) + - metavariable-regex: + metavariable: $SINK + regex: ^(after|append|html|prepend|replaceWith|wrap)$ + - focus-metavariable: $QUERY + pattern-sanitizers: + - patterns: + - pattern-either: + - pattern: $sce.getTrustedHtml(...) + - pattern: $sanitize(...) + - pattern: DOMPurify.sanitize(...) +- id: javascript.angular.security.detect-angular-open-redirect.detect-angular-open-redirect + message: >- + Use of $window.location.href can lead to open-redirect if user input is used for redirection. + metadata: + asvs: + section: V5 Validation, Sanitization and Encoding + control_id: 5.5.1 Insecue Redirect + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x13-V5-Validation-Sanitization-Encoding.md#v51-input-validation + version: '4' + references: + - https://docs.angularjs.org/api/ng/service/$sce#trustAsJs + - https://owasp.org/www-chapter-london/assets/slides/OWASPLondon20170727_AngularJS.pdf + category: security + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + technology: + - angular + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + languages: + - javascript + - typescript + severity: ERROR + patterns: + - pattern: | + $window.location.href = ... + - pattern-not: | + $window.location.href = "..." +- id: javascript.angular.security.detect-angular-resource-loading.detect-angular-resource-loading + message: >- + $sceDelegateProvider allowlisting can introduce security issues if wildcards are used. + metadata: + references: + - https://docs.angularjs.org/api/ng/service/$sce#trustAsJs + - https://owasp.org/www-chapter-london/assets/slides/OWASPLondon20170727_AngularJS.pdf + category: security + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + technology: + - angular + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + languages: + - javascript + - typescript + severity: WARNING + pattern-either: + - pattern: | + $sceDelegateProvider.resourceUrlWhitelist([...,'**',...]); + - patterns: + - pattern: | + $sceDelegateProvider.resourceUrlWhitelist([...,$DOM,...]); + - metavariable-regex: + metavariable: $DOM + regex: ^'.*\*\*.+'$ +- id: javascript.angular.security.detect-angular-sce-disabled.detect-angular-sce-disabled + message: >- + $sceProvider is set to false. Disabling Strict Contextual escaping (SCE) in an AngularJS application + could provide additional attack surface for XSS vulnerabilities. + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + references: + - https://docs.angularjs.org/api/ng/service/$sce + - https://owasp.org/www-chapter-london/assets/slides/OWASPLondon20170727_AngularJS.pdf + category: security + technology: + - angular + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: HIGH + impact: MEDIUM + confidence: HIGH + languages: + - javascript + - typescript + severity: ERROR + pattern: | + $sceProvider.enabled(false); +- id: javascript.angular.security.detect-angular-trust-as-css.detect-angular-trust-as-css-method + message: >- + The use of $sce.trustAsCss can be dangerous if unsanitized user input flows through this API. + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + references: + - https://docs.angularjs.org/api/ng/service/$sce#trustAsCss + - https://owasp.org/www-chapter-london/assets/slides/OWASPLondon20170727_AngularJS.pdf + category: security + technology: + - angular + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + languages: + - javascript + - typescript + severity: WARNING + patterns: + - pattern-either: + - pattern: | + $SOURCE = $scope.$INPUT; + $sce.trustAsCss($SOURCE); + - pattern: | + $sce.trustAsCss($scope.$INPUT); + - pattern-inside: | + app.controller(..., function($scope,$sce){ + ... + }); +- id: javascript.angular.security.detect-angular-trust-as-html-method.detect-angular-trust-as-html-method + message: >- + The use of $sce.trustAsHtml can be dangerous if unsanitized user input flows through this API. + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + references: + - https://docs.angularjs.org/api/ng/service/$sce#trustAsHtml + - https://owasp.org/www-chapter-london/assets/slides/OWASPLondon20170727_AngularJS.pdf + category: security + technology: + - angular + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + languages: + - javascript + - typescript + severity: WARNING + patterns: + - pattern-either: + - pattern: | + $SOURCE = $scope.$INPUT; + $sce.trustAsHtml($SOURCE); + - pattern: | + $sce.trustAsHtml($scope.$INPUT); + - pattern-inside: | + app.controller(..., function($scope,$sce){ + ... + }); +- id: javascript.angular.security.detect-angular-trust-as-js-method.detect-angular-trust-as-js-method + message: >- + The use of $sce.trustAsJs can be dangerous if unsanitized user input flows through this API. + metadata: + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + references: + - https://docs.angularjs.org/api/ng/service/$sce#trustAsJs + - https://owasp.org/www-chapter-london/assets/slides/OWASPLondon20170727_AngularJS.pdf + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + category: security + technology: + - angular + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + languages: + - javascript + - typescript + severity: WARNING + patterns: + - pattern-either: + - pattern: | + $SOURCE = $scope.$INPUT; + $sce.trustAsJs($SOURCE); + - pattern: | + $sce.trustAsJs($scope.$INPUT); + - pattern-inside: | + app.controller(..., function($scope,$sce){ + ... + }); +- id: javascript.angular.security.detect-angular-trust-as-method.detect-angular-trust-as-method + message: >- + The use of $sce.trustAs can be dangerous if unsanitized user input flows through this API. + metadata: + references: + - https://docs.angularjs.org/api/ng/service/$sce + - https://owasp.org/www-chapter-london/assets/slides/OWASPLondon20170727_AngularJS.pdf + category: security + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + technology: + - angular + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: LOW + impact: MEDIUM + confidence: MEDIUM + languages: + - javascript + - typescript + severity: WARNING + mode: taint + pattern-sources: + - patterns: + - pattern-inside: | + app.controller(..., function($scope,$sce) { + ... + }); + - pattern: $scope.$X + pattern-sinks: + - pattern: $sce.trustAs(...) + - pattern: $sce.trustAsHtml(...) +- id: javascript.angular.security.detect-angular-trust-as-resourceurl-method.detect-angular-trust-as-resourceurl-method + message: >- + The use of $sce.trustAsResourceUrl can be dangerous if unsanitized user input flows through this API. + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + references: + - https://docs.angularjs.org/api/ng/service/$sce#trustAsResourceUrl + - https://owasp.org/www-chapter-london/assets/slides/OWASPLondon20170727_AngularJS.pdf + category: security + technology: + - angular + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + languages: + - javascript + - typescript + severity: WARNING + patterns: + - pattern-either: + - pattern: | + $SOURCE = $scope.$INPUT; + $sce.trustAsResourceUrl($SOURCE); + - pattern: | + $sce.trustAsResourceUrl($scope.$INPUT); + - pattern-inside: | + app.controller(..., function($scope,$sce){ + ... + }); +- id: javascript.angular.security.detect-angular-trust-as-url-method.detect-angular-trust-as-url-method + message: >- + The use of $sce.trustAsUrl can be dangerous if unsanitized user input flows through this API. + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + references: + - https://docs.angularjs.org/api/ng/service/$sce#trustAsUrl + - https://owasp.org/www-chapter-london/assets/slides/OWASPLondon20170727_AngularJS.pdf + category: security + technology: + - angular + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + languages: + - javascript + - typescript + severity: WARNING + patterns: + - pattern-either: + - pattern: | + $SOURCE = $scope.$INPUT; + $sce.trustAsUrl($SOURCE); + - pattern: | + $sce.trustAsUrl($scope.$INPUT); + - pattern-inside: | + app.controller(..., function($scope,$sce){ + ... + }); +- id: javascript.angular.security.detect-third-party-angular-translate.detect-angular-translateprovider-translations-method + message: >- + The use of $translateProvider.translations method can be dangerous if user input is provided to this + API. + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + references: + - https://docs.angularjs.org/api/ng/service/$sce#trustAsUrl + - https://owasp.org/www-chapter-london/assets/slides/OWASPLondon20170727_AngularJS.pdf + category: security + technology: + - angular + - typescript + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + languages: + - javascript + severity: WARNING + patterns: + - pattern: | + $translateProvider.translations(...,$SOURCE); + - pattern-inside: | + app.controller(..., function($scope,$sce){ + ... + }); +- id: javascript.apollo.security.apollo-axios-ssrf.apollo-axios-ssrf + message: >- + User-controllable argument $DATAVAL to $METHOD passed to Axios + via internal handler $INNERFUNC. + This could be a server-side request forgery. A user could call + a restricted API or leak internal headers to an unauthorized party. + Validate your user arguments against an allowlist of known URLs, or + consider refactoring so that user-controlled data is not necessary. + metadata: + owasp: + - A10:2021 - Server-Side Request Forgery (SSRF) + cwe: + - 'CWE-918: Server-Side Request Forgery (SSRF)' + category: security + technology: + - apollo + - axios + references: + - https://www.cvedetails.com/cve/CVE-2020-28168/ + - https://owasp.org/www-community/attacks/Server_Side_Request_Forgery + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + languages: + - javascript + severity: WARNING + patterns: + - pattern: const $RESPONSE = await axios.request($INNERARG,...) + - pattern-inside: | + Query: { + $METHOD(parent, args, context, info) { + ... + $DATA = args.$DATAVAL + ... + async function $INNERFUNC(...,$INNERARG,...){ + ... + } + ... + return $INNERFUNC(...,$DATA,...) + } + } +- id: javascript.argon2.security.unsafe-argon2-config.unsafe-argon2-config + message: >- + Prefer Argon2id where possible. Per RFC9016, section 4 IETF recommends selecting Argon2id unless you + can guarantee an adversary has no direct access to the computing environment. + metadata: + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html + - https://eprint.iacr.org/2016/759.pdf + - https://www.cs.tau.ac.il/~tromer/papers/cache-joc-20090619.pdf + - https://datatracker.ietf.org/doc/html/rfc9106#section-4 + category: security + cwe: + - 'CWE-916: Use of Password Hash With Insufficient Computational Effort' + technology: + - argon2 + - cryptography + owasp: + - A02:2021 - Cryptographic Failures + subcategory: + - vuln + impact: LOW + likelihood: HIGH + confidence: MEDIUM + languages: + - javascript + - typescript + severity: WARNING + mode: taint + pattern-sources: + - patterns: + - pattern-inside: | + $ARGON = require('argon2'); + ... + - pattern: | + {type: ...} + pattern-sinks: + - patterns: + - pattern: | + $Y + - pattern-inside: | + $ARGON.hash(...,$Y) + pattern-sanitizers: + - patterns: + - pattern: | + {type: $ARGON.argon2id} + ... +- id: javascript.audit.detect-replaceall-sanitization.detect-replaceall-sanitization + message: >- + Detected a call to `$FUNC()` in an attempt to HTML escape the string `$STR`. + Manually sanitizing input through a manually built list can be circumvented + in many situations, and it's better to use a well known sanitization library + such as `sanitize-html` or `DOMPurify`. + metadata: + category: security + technology: + - javascript + - typescript + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + references: + - https://www.npmjs.com/package/dompurify + - https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: + - javascript + - typescript + severity: INFO + patterns: + - pattern-either: + - pattern: $STR.$FUNC('<', '<') + - pattern: $STR.$FUNC('>', '>') + - pattern: $STR.$FUNC('"', '"') + - pattern: $STR.$FUNC("'", ''') + - pattern: $STR.$FUNC('&', '&') + - metavariable-regex: + metavariable: $FUNC + regex: (replace|replaceAll) +- id: javascript.aws-lambda.security.detect-child-process.detect-child-process + message: >- + Allowing spawning arbitrary programs or running shell processes with arbitrary arguments may end up + in a command injection vulnerability. + Try to avoid non-literal values for the command string. + If it is not possible, then do not let running arbitrary commands, use a white list for inputs. + metadata: + cwe: + - "CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')" + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + category: security + technology: + - javascript + - aws-lambda + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: HIGH + confidence: MEDIUM + references: + - https://owasp.org/Top10/A03_2021-Injection + languages: + - javascript + - typescript + severity: ERROR + mode: taint + pattern-sources: + - patterns: + - pattern: $EVENT + - pattern-either: + - pattern-inside: | + exports.handler = function ($EVENT, ...) { + ... + } + - pattern-inside: | + function $FUNC ($EVENT, ...) {...} + ... + exports.handler = $FUNC + - pattern-inside: | + $FUNC = function ($EVENT, ...) {...} + ... + exports.handler = $FUNC + pattern-sinks: + - patterns: + - focus-metavariable: $CMD + - pattern-either: + - pattern: exec($CMD,...) + - pattern: execSync($CMD,...) + - pattern: spawn($CMD,...) + - pattern: spawnSync($CMD,...) + - pattern: $CP.exec($CMD,...) + - pattern: $CP.execSync($CMD,...) + - pattern: $CP.spawn($CMD,...) + - pattern: $CP.spawnSync($CMD,...) + - pattern-either: + - pattern-inside: | + require('child_process') + ... + - pattern-inside: | + import 'child_process' + ... +- id: javascript.aws-lambda.security.dynamodb-request-object.dynamodb-request-object + message: >- + Detected DynamoDB query params that are tainted by `$EVENT` object. This could lead to NoSQL injection + if the variable is user-controlled + and not properly sanitized. Explicitly assign query params instead of passing data from `$EVENT` directly + to DynamoDB client. + metadata: + cwe: + - 'CWE-943: Improper Neutralization of Special Elements in Data Query Logic' + owasp: + - A01:2017 - Injection + category: security + technology: + - javascript + - aws-lambda + - dynamodb + subcategory: + - vuln + likelihood: MEDIUM + impact: HIGH + confidence: MEDIUM + references: + - https://owasp.org/Top10/A03_2021-Injection + languages: + - javascript + - typescript + severity: ERROR + mode: taint + pattern-sources: + - patterns: + - pattern: $EVENT + - pattern-either: + - pattern-inside: | + exports.handler = function ($EVENT, ...) { + ... + } + - pattern-inside: | + function $FUNC ($EVENT, ...) {...} + ... + exports.handler = $FUNC + - pattern-inside: | + $FUNC = function ($EVENT, ...) {...} + ... + exports.handler = $FUNC + pattern-sinks: + - patterns: + - focus-metavariable: $SINK + - pattern: | + $DC.$METHOD($SINK, ...) + - metavariable-regex: + metavariable: $METHOD + regex: (query|send|scan|delete|put|transactWrite|update|batchExecuteStatement|executeStatement|executeTransaction|transactWriteItems) + - pattern-either: + - pattern-inside: | + $DC = new $AWS.DocumentClient(...); + ... + - pattern-inside: | + $DC = new $AWS.DynamoDB(...); + ... + - pattern-inside: | + $DC = new DynamoDBClient(...); + ... + - pattern-inside: | + $DC = DynamoDBDocumentClient.from(...); + ... + pattern-sanitizers: + - patterns: + - pattern: | + {...} +- id: javascript.aws-lambda.security.knex-sqli.knex-sqli + message: >- + Detected SQL statement that is tainted by `$EVENT` object. This could lead to SQL injection if the + variable is user-controlled + and not properly sanitized. In order to prevent SQL injection, + use parameterized queries or prepared statements instead. + You can use parameterized statements like so: + `knex.raw('SELECT $1 from table', [userinput])` + metadata: + references: + - https://knexjs.org/#Builder-fromRaw + - https://knexjs.org/#Builder-whereRaw + category: security + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + cwe: + - "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')" + technology: + - aws-lambda + - knex + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: HIGH + confidence: MEDIUM + languages: + - javascript + - typescript + severity: WARNING + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - pattern-inside: | + exports.handler = function ($EVENT, ...) { + ... + } + - pattern-inside: | + function $FUNC ($EVENT, ...) {...} + ... + exports.handler = $FUNC + - pattern-inside: | + $FUNC = function ($EVENT, ...) {...} + ... + exports.handler = $FUNC + - pattern: $EVENT + pattern-sinks: + - patterns: + - focus-metavariable: $QUERY + - pattern-either: + - pattern: $KNEX.fromRaw($QUERY, ...) + - pattern: $KNEX.whereRaw($QUERY, ...) + - pattern: $KNEX.raw($QUERY, ...) + - pattern-either: + - pattern-inside: | + require('knex') + ... + - pattern-inside: | + import 'knex' + ... +- id: javascript.aws-lambda.security.mysql-sqli.mysql-sqli + message: >- + Detected SQL statement that is tainted by `$EVENT` object. This could lead to SQL injection if the + variable is user-controlled + and not properly sanitized. In order to prevent SQL injection, + use parameterized queries or prepared statements instead. + You can use parameterized statements like so: + `connection.query('SELECT $1 from table', [userinput])` + metadata: + references: + - https://www.npmjs.com/package/mysql2 + category: security + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + cwe: + - "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')" + technology: + - aws-lambda + - mysql + - mysql2 + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: HIGH + confidence: MEDIUM + languages: + - javascript + - typescript + severity: WARNING + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - pattern-inside: | + exports.handler = function ($EVENT, ...) { + ... + } + - pattern-inside: | + function $FUNC ($EVENT, ...) {...} + ... + exports.handler = $FUNC + - pattern-inside: | + $FUNC = function ($EVENT, ...) {...} + ... + exports.handler = $FUNC + - pattern: $EVENT + pattern-sinks: + - patterns: + - focus-metavariable: $QUERY + - pattern-either: + - pattern: $POOL.query($QUERY, ...) + - pattern: $POOL.execute($QUERY, ...) + - pattern-either: + - pattern-inside: | + require('mysql') + ... + - pattern-inside: | + require('mysql2') + ... + - pattern-inside: | + require('mysql2/promise') + ... + - pattern-inside: | + import 'mysql' + ... + - pattern-inside: | + import 'mysql2' + ... + - pattern-inside: | + import 'mysql2/promise' + ... +- id: javascript.aws-lambda.security.pg-sqli.pg-sqli + message: >- + Detected SQL statement that is tainted by `$EVENT` object. This could lead to SQL injection if the + variable is user-controlled + and not properly sanitized. In order to prevent SQL injection, + use parameterized queries or prepared statements instead. + You can use parameterized statements like so: + `connection.query('SELECT $1 from table', [userinput])` + metadata: + references: + - https://node-postgres.com/features/queries + category: security + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + cwe: + - "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')" + technology: + - aws-lambda + - postgres + - pg + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: HIGH + confidence: MEDIUM + languages: + - javascript + - typescript + severity: WARNING + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - pattern-inside: | + exports.handler = function ($EVENT, ...) { + ... + } + - pattern-inside: | + function $FUNC ($EVENT, ...) {...} + ... + exports.handler = $FUNC + - pattern-inside: | + $FUNC = function ($EVENT, ...) {...} + ... + exports.handler = $FUNC + - pattern: $EVENT + pattern-sinks: + - patterns: + - focus-metavariable: $QUERY + - pattern-either: + - pattern: $DB.query($QUERY, ...) + - pattern-either: + - pattern-inside: | + require('pg') + ... + - pattern-inside: | + import 'pg' + ... +- id: javascript.aws-lambda.security.sequelize-sqli.sequelize-sqli + message: >- + Detected SQL statement that is tainted by `$EVENT` object. This could lead to SQL injection if the + variable is user-controlled + and not properly sanitized. In order to prevent SQL injection, + use parameterized queries or prepared statements instead. + You can use parameterized statements like so: + `sequelize.query('SELECT * FROM projects WHERE status = ?', { replacements: ['active'], type: QueryTypes.SELECT + });` + metadata: + references: + - https://sequelize.org/master/manual/raw-queries.html + category: security + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + cwe: + - "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')" + technology: + - aws-lambda + - sequelize + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: HIGH + confidence: MEDIUM + languages: + - javascript + - typescript + severity: WARNING + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - pattern-inside: | + exports.handler = function ($EVENT, ...) { + ... + } + - pattern-inside: | + function $FUNC ($EVENT, ...) {...} + ... + exports.handler = $FUNC + - pattern-inside: | + $FUNC = function ($EVENT, ...) {...} + ... + exports.handler = $FUNC + - pattern: $EVENT + pattern-sinks: + - patterns: + - focus-metavariable: $QUERY + - pattern-either: + - pattern: $DB.query($QUERY, ...) + - pattern-either: + - pattern-inside: | + require('sequelize') + ... + - pattern-inside: | + import 'sequelize' + ... +- id: javascript.aws-lambda.security.tainted-eval.tainted-eval + message: >- + The `eval()` function evaluates JavaScript code represented as a string. + Executing JavaScript from a string is an enormous security risk. + It is far too easy for a bad actor to run arbitrary code when you use `eval()`. + Ensure evaluated content is not definable by external sources. + metadata: + cwe: + - "CWE-95: Improper Neutralization of Directives in Dynamically Evaluated Code ('Eval Injection')" + owasp: + - A03:2021 - Injection + category: security + technology: + - javascript + - aws-lambda + subcategory: + - vuln + likelihood: MEDIUM + impact: HIGH + confidence: LOW + references: + - https://owasp.org/Top10/A03_2021-Injection + languages: + - javascript + - typescript + severity: WARNING + mode: taint + pattern-sources: + - patterns: + - pattern: $EVENT + - pattern-either: + - pattern-inside: | + exports.handler = function ($EVENT, ...) { + ... + } + - pattern-inside: | + function $FUNC ($EVENT, ...) {...} + ... + exports.handler = $FUNC + - pattern-inside: | + $FUNC = function ($EVENT, ...) {...} + ... + exports.handler = $FUNC + pattern-sinks: + - patterns: + - focus-metavariable: $CODE + - pattern-either: + - pattern: eval($CODE) + - pattern: Function(...,$CODE) + - pattern: new Function(...,$CODE) +- id: javascript.aws-lambda.security.tainted-html-response.tainted-html-response + message: >- + Detected user input flowing into an HTML response. You may be + accidentally bypassing secure methods + of rendering HTML by manually constructing HTML and this could create a cross-site + scripting vulnerability, which could let attackers steal sensitive user data. + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + category: security + technology: + - aws-lambda + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + references: + - https://owasp.org/Top10/A03_2021-Injection + languages: + - javascript + - typescript + severity: WARNING + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - pattern-inside: | + exports.handler = function ($EVENT, ...) { + ... + } + - pattern-inside: | + function $FUNC ($EVENT, ...) {...} + ... + exports.handler = $FUNC + - pattern-inside: | + $FUNC = function ($EVENT, ...) {...} + ... + exports.handler = $FUNC + - pattern: $EVENT + pattern-sinks: + - patterns: + - focus-metavariable: $BODY + - pattern-inside: | + {..., headers: {..., 'Content-Type': 'text/html', ...}, body: $BODY, ... } +- id: javascript.aws-lambda.security.tainted-html-string.tainted-html-string + message: >- + Detected user input flowing into a manually constructed HTML string. You may be accidentally bypassing + secure methods + of rendering HTML by manually constructing HTML and this could create a cross-site scripting vulnerability, + which could + let attackers steal sensitive user data. To be sure this is safe, check that the HTML is rendered + safely. Otherwise, use + templates which will safely render HTML instead. + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + category: security + technology: + - aws-lambda + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + references: + - https://owasp.org/Top10/A03_2021-Injection + languages: + - javascript + - typescript + severity: WARNING + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - pattern-inside: | + exports.handler = function ($EVENT, ...) { + ... + } + - pattern-inside: | + function $FUNC ($EVENT, ...) {...} + ... + exports.handler = $FUNC + - pattern-inside: | + $FUNC = function ($EVENT, ...) {...} + ... + exports.handler = $FUNC + - pattern: $EVENT + pattern-sinks: + - patterns: + - pattern-either: + - patterns: + - pattern-either: + - pattern: | + "$HTMLSTR" + $EXPR + - pattern: | + "$HTMLSTR".concat(...) + - pattern: $UTIL.format($HTMLSTR, ...) + - pattern: format($HTMLSTR, ...) + - metavariable-pattern: + metavariable: $HTMLSTR + language: generic + pattern: <$TAG ... + - patterns: + - pattern: | + `...${...}...` + - pattern-regex: | + .*<\w+.* + - pattern-not-inside: | + console.$LOG(...) +- id: javascript.aws-lambda.security.tainted-sql-string.tainted-sql-string + message: >- + Detected user input used to manually construct a SQL string. This is usually + bad practice because manual construction could accidentally result in a SQL + injection. An attacker could use a SQL injection to steal or modify contents + of the database. Instead, use a parameterized query which is available + by default in most database engines. Alternatively, consider using an + object-relational mapper (ORM) such as Sequelize which will protect your queries. + metadata: + references: + - https://owasp.org/www-community/attacks/SQL_Injection + category: security + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + cwe: + - "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')" + technology: + - aws-lambda + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: LOW + impact: MEDIUM + confidence: MEDIUM + languages: + - javascript + - typescript + severity: ERROR + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - pattern-inside: | + exports.handler = function ($EVENT, ...) { + ... + } + - pattern-inside: | + function $FUNC ($EVENT, ...) {...} + ... + exports.handler = $FUNC + - pattern-inside: | + $FUNC = function ($EVENT, ...) {...} + ... + exports.handler = $FUNC + - pattern: $EVENT + pattern-sinks: + - patterns: + - pattern-either: + - patterns: + - pattern-either: + - pattern: | + "$SQLSTR" + $EXPR + - pattern: | + "$SQLSTR".concat(...) + - pattern: util.format($SQLSTR, ...) + - metavariable-regex: + metavariable: $SQLSTR + regex: .*\b(?i)(select|delete|insert|create|update|alter|drop)\b.* + - patterns: + - pattern: | + `...${...}...` + - pattern-regex: | + .*\b(?i)(select|delete|insert|create|update|alter|drop)\b.* + - pattern-not-inside: | + console.$LOG(...) +- id: javascript.aws-lambda.security.vm-runincontext-injection.vm-runincontext-injection + message: >- + The `vm` module enables compiling and running code within V8 Virtual Machine contexts. + The `vm` module is not a security mechanism. Do not use it to run untrusted code. + If code passed to `vm` functions is controlled by user input it could result in command injection. + Do not let user input in `vm` functions. + metadata: + owasp: + - A03:2021 - Injection + cwe: + - "CWE-94: Improper Control of Generation of Code ('Code Injection')" + category: security + technology: + - javascript + - aws-lambda + cwe2022-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + references: + - https://owasp.org/Top10/A03_2021-Injection + languages: + - javascript + - typescript + severity: ERROR + mode: taint + pattern-sources: + - patterns: + - pattern: $EVENT + - pattern-either: + - pattern-inside: | + exports.handler = function ($EVENT, ...) { + ... + } + - pattern-inside: | + function $FUNC ($EVENT, ...) {...} + ... + exports.handler = $FUNC + - pattern-inside: | + $FUNC = function ($EVENT, ...) {...} + ... + exports.handler = $FUNC + pattern-sinks: + - patterns: + - pattern-either: + - pattern-inside: | + require('vm'); + ... + - pattern-inside: | + import 'vm' + ... + - pattern-either: + - pattern: $VM.runInContext($X,...) + - pattern: $VM.runInNewContext($X,...) + - pattern: $VM.runInThisContext($X,...) + - pattern: $VM.compileFunction($X,...) + - pattern: new $VM.Script($X,...) + - pattern: new $VM.SourceTextModule($X,...) + - pattern: runInContext($X,...) + - pattern: runInNewContext($X,...) + - pattern: runInThisContext($X,...) + - pattern: compileFunction($X,...) + - pattern: new Script($X,...) + - pattern: new SourceTextModule($X,...) +- id: javascript.bluebird.security.audit.tofastproperties-code-execution.tofastproperties-code-execution + message: >- + Potential arbitrary code execution, whatever is provided to `toFastProperties` is sent straight to + eval() + metadata: + cwe: + - "CWE-94: Improper Control of Generation of Code ('Code Injection')" + owasp: + - A03:2021 - Injection + category: security + technology: + - bluebird + references: + - http://bluebirdjs.com/docs/getting-started.html + cwe2022-top25: true + subcategory: + - vuln + likelihood: LOW + impact: MEDIUM + confidence: LOW + languages: + - javascript + - typescript + severity: WARNING + mode: taint + pattern-sources: + - patterns: + - pattern-inside: function ... (..., $ARG,...) {...} + - focus-metavariable: $ARG + pattern-sinks: + - patterns: + - pattern-either: + - pattern: $UTIL.toFastProperties($SINK,...) + - pattern: toFastProperties($SINK,...) + - pattern-either: + - pattern-inside: | + $BB = require('bluebird'); + ... + - pattern-inside: | + import 'bluebird'; + ... + - focus-metavariable: $SINK +- id: javascript.browser.security.dom-based-xss.dom-based-xss + message: >- + Detected possible DOM-based XSS. This occurs because a portion of the URL is being used + to construct an element added directly to the page. For example, a malicious actor could + send someone a link like this: http://www.some.site/page.html?default= + which would add the script to the page. + Consider allowlisting appropriate values or using an approach which does not involve the URL. + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + references: + - https://owasp.org/www-community/attacks/DOM_Based_XSS + category: security + technology: + - browser + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: + - javascript + - typescript + severity: ERROR + pattern-either: + - pattern: document.write(<... document.location.$W ...>) + - pattern: document.write(<... location.$W ...>) +- id: javascript.browser.security.eval-detected.eval-detected + message: >- + Detected the use of eval(). eval() can be dangerous if used to evaluate + dynamic content. If this content can be input from outside the program, this + may be a code injection vulnerability. Ensure evaluated content is not definable + by external sources. + metadata: + cwe: + - "CWE-95: Improper Neutralization of Directives in Dynamically Evaluated Code ('Eval Injection')" + owasp: + - A03:2021 - Injection + asvs: + section: V5 Validation, Sanitization and Encoding + control_id: 5.2.4 Dynamic Code Execution Features + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x13-V5-Validation-Sanitization-Encoding.md#v52-sanitization-and-sandboxing + version: '4' + category: security + technology: + - browser + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + references: + - https://owasp.org/Top10/A03_2021-Injection + languages: + - javascript + - typescript + severity: WARNING + patterns: + - pattern-not: eval("...") + - pattern: eval(...) +- id: javascript.browser.security.insecure-document-method.insecure-document-method + message: >- + User controlled data in methods like `innerHTML`, `outerHTML` or `document.write` is an anti-pattern + that can lead to XSS vulnerabilities + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + category: security + technology: + - browser + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + references: + - https://owasp.org/Top10/A03_2021-Injection + languages: + - javascript + - typescript + severity: ERROR + patterns: + - pattern-either: + - pattern: | + $EL.innerHTML = $HTML; + - pattern: | + $EL.outerHTML = $HTML; + - pattern: document.write(...) + - pattern-not: | + $EL.innerHTML = "..."; + - pattern-not: | + $EL.outerHTML = "..."; + - pattern-not: document.write("...") +- id: javascript.browser.security.insecure-innerhtml.insecure-innerhtml + message: >- + User controlled data in a `$EL.innerHTML` is an anti-pattern that can lead to XSS vulnerabilities + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + category: security + technology: + - browser + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + references: + - https://owasp.org/Top10/A03_2021-Injection + languages: + - javascript + - typescript + severity: ERROR + patterns: + - pattern: | + $EL.innerHTML = $HTML; + - pattern-not: | + $EL.innerHTML = "..."; +- id: javascript.browser.security.insufficient-postmessage-origin-validation.insufficient-postmessage-origin-validation + message: >- + No validation of origin is done by the addEventListener API. It may be possible to exploit this flaw + to perform Cross Origin attacks such as Cross-Site Scripting(XSS). + metadata: + owasp: + - A08:2021 - Software and Data Integrity Failures + cwe: + - 'CWE-345: Insufficient Verification of Data Authenticity' + category: security + technology: + - browser + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + references: + - https://owasp.org/Top10/A08_2021-Software_and_Data_Integrity_Failures + languages: + - javascript + - typescript + severity: WARNING + pattern-either: + - patterns: + - pattern: | + window.addEventListener('message', $FUNC, ...) + - metavariable-pattern: + patterns: + - pattern: | + function($OBJ) { ... } + - pattern-not: | + function($OBJ) { ... if (<... $OBJ.origin ...>) { ... } ... } + metavariable: $FUNC + - patterns: + - pattern-either: + - pattern-inside: | + function $FNAME($OBJ) { $CONTEXT } + ... + - pattern-inside: | + $FNAME = (...) => { $CONTEXT } + ... + - pattern: | + window.addEventListener('message', $FNAME,...) + - metavariable-pattern: + patterns: + - pattern-not: | + ... if (<... $OBJ.origin ...>) { ... } ... + metavariable: $CONTEXT +- id: javascript.browser.security.open-redirect-from-function.js-open-redirect-from-function + message: >- + The application accepts potentially user-controlled input `$PROP` which + can control the location of the current window context. This can lead two + types of vulnerabilities open-redirection and Cross-Site-Scripting + (XSS) with JavaScript URIs. It is recommended to validate + user-controllable input before allowing it to control the redirection. + metadata: + confidence: LOW + cwe: + - "CWE-601: URL Redirection to Untrusted Site ('Open Redirect')" + owasp: + - A01:2021 - Broken Access Control + asvs: + section: V5 Validation, Sanitization and Encoding + control_id: 5.5.1 Insecue Redirect + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x13-V5-Validation-Sanitization-Encoding.md#v51-input-validation + version: '4' + category: security + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html + technology: + - browser + license: Commons Clause License Condition v1.0[LGPL-2.1-only] + subcategory: + - vuln + likelihood: LOW + impact: MEDIUM + languages: + - javascript + - typescript + severity: INFO + mode: taint + pattern-sources: + - patterns: + - pattern-inside: | + function ... (..., $PROP, ...) { ... } + - focus-metavariable: $PROP + pattern-sinks: + - patterns: + - pattern-either: + - pattern: location.href = $SINK + - pattern: window.location.href = $SINK + - pattern: this.window.location.href = $SINK + - pattern: this.location.href = $SINK + - pattern: location.replace($SINK) + - pattern: window.location.replace($SINK) + - pattern: this.window.location.replace($SINK) + - pattern: this.location.replace($SINK) + - focus-metavariable: $SINK + - metavariable-pattern: + patterns: + - pattern-not: | + "..." + $VALUE + - pattern-not: | + `...${$VALUE}` + metavariable: $SINK +- id: javascript.browser.security.open-redirect.js-open-redirect + message: >- + The application accepts potentially user-controlled input `$PROP` which + can control the location of the current window context. This can lead two + types of vulnerabilities open-redirection and Cross-Site-Scripting + (XSS) with JavaScript URIs. It is recommended to validate + user-controllable input before allowing it to control the redirection. + options: + interfile: true + metadata: + interfile: true + cwe: + - "CWE-601: URL Redirection to Untrusted Site ('Open Redirect')" + owasp: + - A01:2021 - Broken Access Control + asvs: + section: V5 Validation, Sanitization and Encoding + control_id: 5.5.1 Insecue Redirect + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x13-V5-Validation-Sanitization-Encoding.md#v51-input-validation + version: '4' + category: security + confidence: HIGH + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html + technology: + - browser + license: Commons Clause License Condition v1.0[LGPL-2.1-only] + subcategory: + - vuln + likelihood: HIGH + impact: MEDIUM + languages: + - javascript + - typescript + severity: WARNING + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - pattern-inside: | + $PROP = new URLSearchParams($WINDOW. ... .location.search).get('...') + ... + - pattern-inside: | + $PROP = new URLSearchParams(location.search).get('...') + ... + - pattern-inside: | + $PROP = new URLSearchParams($WINDOW. ... .location.hash.substring(1)).get('...') + ... + - pattern-inside: | + $PROP = new URLSearchParams(location.hash.substring(1)).get('...') + ... + - pattern: $PROP + - patterns: + - pattern-either: + - pattern-inside: | + $PROPS = new URLSearchParams($WINDOW. ... .location.search) + ... + - pattern-inside: | + $PROPS = new URLSearchParams(location.search) + ... + - pattern-inside: | + $PROPS = new URLSearchParams($WINDOW. ... .location.hash.substring(1)) + ... + - pattern-inside: | + $PROPS = new URLSearchParams(location.hash.substring(1)) + ... + - pattern: $PROPS.get('...') + - patterns: + - pattern-either: + - pattern-inside: | + $PROPS = new URL($WINDOW. ... .location.href) + ... + - pattern-inside: | + $PROPS = new URL(location.href) + ... + - pattern: $PROPS.searchParams.get('...') + - patterns: + - pattern-either: + - pattern-inside: | + $PROPS = new URL($WINDOW. ... .location.href).searchParams.get('...') + ... + - pattern-inside: | + $PROPS = new URL(location.href).searchParams.get('...') + ... + - pattern: $PROPS + pattern-sinks: + - patterns: + - pattern-either: + - pattern: location.href = $SINK + - pattern: $THIS. ... .location.href = $SINK + - pattern: location.replace($SINK) + - pattern: $THIS. ... .location.replace($SINK) + - pattern: location = $SINK + - pattern: $WINDOW. ... .location = $SINK + - focus-metavariable: $SINK + - metavariable-pattern: + patterns: + - pattern-not: | + "..." + $VALUE + - pattern-not: | + `...${$VALUE}` + metavariable: $SINK +- id: javascript.browser.security.raw-html-concat.raw-html-concat + message: User controlled data in a HTML string may result in XSS + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + references: + - https://owasp.org/www-community/attacks/xss/ + category: security + technology: + - browser + license: Commons Clause License Condition v1.0[LGPL-2.1-only] + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + languages: + - javascript + - typescript + severity: WARNING + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - pattern: location.href + - pattern: location.hash + - pattern: location.search + - pattern: $WINDOW. ... .location.href + - pattern: $WINDOW. ... .location.hash + - pattern: $WINDOW. ... .location.search + pattern-sinks: + - patterns: + - pattern-either: + - patterns: + - pattern: $STRING + $EXPR + - pattern-not: $STRING + "..." + - metavariable-pattern: + patterns: + - pattern: <$TAG ... + - pattern-not: <$TAG ...>...... + metavariable: $STRING + language: generic + - patterns: + - pattern: $EXPR + $STRING + - pattern-not: '"..." + $STRING' + - metavariable-pattern: + patterns: + - pattern: '... - + User controlled data in a HTML string may result in XSS + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + references: + - https://owasp.org/www-community/attacks/xss/ + category: security + technology: + - browser + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: + - javascript + - typescript + severity: WARNING + patterns: + - pattern-either: + - patterns: + - pattern: | + [..., $STRING, ...].join(...) + - metavariable-pattern: + metavariable: $STRING + language: generic + patterns: + - pattern-either: + - pattern: | + ... - + The target origin of the window.postMessage() API is set to "*". This could allow for information + disclosure due to the possibility of any origin allowed to receive the message. + metadata: + owasp: + - A08:2021 - Software and Data Integrity Failures + cwe: + - 'CWE-345: Insufficient Verification of Data Authenticity' + category: security + technology: + - browser + subcategory: + - audit + likelihood: HIGH + impact: MEDIUM + confidence: MEDIUM + references: + - https://owasp.org/Top10/A08_2021-Software_and_Data_Integrity_Failures + languages: + - javascript + - typescript + severity: WARNING + pattern: $OBJECT.postMessage(...,'*') +- id: javascript.chrome-remote-interface.security.audit.chrome-remote-interface-compilescript-injection.chrome-remote-interface-compilescript-injection + message: >- + If unverified user data can reach the `compileScript` method it can result in Server-Side Request + Forgery vulnerabilities + metadata: + owasp: + - A10:2021 - Server-Side Request Forgery (SSRF) + cwe: + - 'CWE-918: Server-Side Request Forgery (SSRF)' + category: security + technology: + - chrome-remote-interface + references: + - https://github.com/cyrus-and/chrome-remote-interface + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + languages: + - javascript + - typescript + severity: WARNING + mode: taint + pattern-sources: + - patterns: + - pattern-inside: function ... (..., $ARG,...) {...} + - focus-metavariable: $ARG + pattern-sinks: + - patterns: + - pattern-either: + - pattern-inside: | + require('chrome-remote-interface'); + ... + - pattern-inside: | + import 'chrome-remote-interface'; + ... + - pattern-either: + - pattern: | + $RUNTIME.compileScript({expression: $SINK},...) + - pattern: | + $RUNTIME.evaluate({expression: $SINK},...) + - pattern: | + $PAGE.navigate({url: $SINK},...) + - pattern: | + $RUNTIME.printToPDF({headerTemplate: $SINK},...) + - pattern: | + $RUNTIME.printToPDF({footerTemplate: $SINK},...) + - pattern: | + $PAGE.setDocumentContent({html: $SINK},...) + - focus-metavariable: $SINK +- id: javascript.deno.security.audit.deno-dangerous-run.deno-dangerous-run + message: >- + Detected non-literal calls to Deno.run(). This could lead to a command + injection vulnerability. + metadata: + cwe: + - "CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')" + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + category: security + technology: + - deno + references: + - https://deno.land/manual/examples/subprocess#simple-example + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: LOW + impact: HIGH + confidence: MEDIUM + languages: + - javascript + - typescript + severity: ERROR + mode: taint + pattern-sources: + - patterns: + - pattern-inside: function ... (..., $ARG,...) {...} + - focus-metavariable: $ARG + pattern-sinks: + - patterns: + - pattern-either: + - pattern: | + Deno.run({cmd: [$INPUT,...]},...) + - pattern: | + Deno.run({cmd: ["=~/(sh|bash|ksh|csh|tcsh|zsh)/","-c",$INPUT,...]},...) + - patterns: + - pattern: | + Deno.run({cmd: [$CMD,"-c",$INPUT,...]},...) + - pattern-inside: | + $CMD = "=~/(sh|bash|ksh|csh|tcsh|zsh)/" + ... + - focus-metavariable: $INPUT +- id: javascript.express.security.audit.express-check-csurf-middleware-usage.express-check-csurf-middleware-usage + message: >- + A CSRF middleware was not detected in your express application. Ensure you are either using one such + as `csurf` or `csrf` (see rule references) and/or you are properly doing CSRF validation in + your routes with a token or cookies. + metadata: + category: security + references: + - https://www.npmjs.com/package/csurf + - https://www.npmjs.com/package/csrf + - https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html + cwe: + - 'CWE-352: Cross-Site Request Forgery (CSRF)' + owasp: + - A01:2021 - Broken Access Control + technology: + - javascript + - typescript + - express + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH + confidence: LOW + languages: + - javascript + - typescript + severity: INFO + patterns: + - pattern-inside: | + $EXPRESS = require('express') + ... + - pattern-not-inside: | + import {$CSRF} from 'csurf' + ... + - pattern-not-inside: | + require('csurf') + ... + - pattern-not-inside: | # filter out applications that use this alternate csrf library + import {$CSRF} from 'csrf' + ... + - pattern-not-inside: | # filter out applications that use this alternate csrf library + require('csrf') + ... + - pattern: | + $APP = $EXPRESS() +- id: javascript.express.security.audit.express-check-directory-listing.express-check-directory-listing + message: Directory listing/indexing is enabled, which may lead to disclosure of sensitive directories + and files. It is recommended to disable directory listing unless it is a public resource. If you need + directory listing, ensure that sensitive files are inaccessible when querying the resource. + options: + interfile: true + metadata: + interfile: true + cwe: + - 'CWE-548: Exposure of Information Through Directory Listing' + owasp: + - A06:2017 - Security Misconfiguration + - A01:2021 - Broken Access Control + category: security + technology: + - express + references: + - https://www.npmjs.com/package/serve-index + - https://www.acunetix.com/blog/articles/directory-listing-information-disclosure/ + subcategory: + - vuln + likelihood: HIGH + impact: MEDIUM + confidence: MEDIUM + languages: + - javascript + - typescript + severity: WARNING + patterns: + - pattern-either: + - pattern: | + $APP.use(require('serve-index')(...)) + - patterns: + - pattern-either: + - pattern-inside: | + $SERVEINDEX = require('serve-index') + ... + - pattern-inside: | + import $SERVEINDEX from 'serve-index' + ... + - pattern-inside: | + import * as $SERVEINDEX from 'serve-index' + ... + - pattern-either: + - patterns: + - pattern-inside: | + $VALUE = $SERVEINDEX(...) + ... + - pattern: | + $VALUE(...) + - pattern: | + $APP.use(..., $SERVEINDEX(...), ...) +- id: javascript.express.security.audit.express-cookie-settings.express-cookie-session-default-name + message: >- + Don’t use the default session cookie name + Using the default session cookie name can open your app to attacks. + The security issue posed is similar to X-Powered-By: a potential attacker can use it to fingerprint the server and target attacks accordingly. + severity: WARNING + languages: [javascript, typescript] + metadata: + cwe: + - 'CWE-522: Insufficiently Protected Credentials' + owasp: + - A02:2017 - Broken Authentication + - A04:2021 - Insecure Design + source-rule-url: https://expressjs.com/en/advanced/best-practice-security.html + category: security + technology: + - express + cwe2021-top25: true + subcategory: + - vuln + likelihood: HIGH + impact: LOW + confidence: MEDIUM + references: + - https://owasp.org/Top10/A04_2021-Insecure_Design + patterns: + - pattern-either: + - pattern-inside: | + $SESSION = require('cookie-session'); + ... + - pattern-inside: | + $SESSION = require('express-session'); + ... + - pattern: $SESSION(...) + - pattern-not-inside: $SESSION(<... {name:...} ...>,...) + - pattern-not-inside: | + $OPTS = <... {name:...} ...>; + ... + $SESSION($OPTS,...); + - pattern-not-inside: | + $OPTS = ...; + ... + $OPTS.name = ...; + ... + $SESSION($OPTS,...); +- id: javascript.express.security.audit.express-cookie-settings.express-cookie-session-no-secure + message: >- + Default session middleware settings: `secure` not set. + It ensures the browser only sends the cookie over HTTPS. + severity: WARNING + languages: [javascript, typescript] + metadata: + cwe: + - 'CWE-522: Insufficiently Protected Credentials' + owasp: + - A02:2017 - Broken Authentication + - A04:2021 - Insecure Design + source-rule-url: https://expressjs.com/en/advanced/best-practice-security.html + category: security + technology: + - express + cwe2021-top25: true + subcategory: + - vuln + likelihood: HIGH + impact: LOW + confidence: MEDIUM + references: + - https://owasp.org/Top10/A04_2021-Insecure_Design + patterns: + - pattern-either: + - pattern-inside: | + $SESSION = require('cookie-session'); + ... + - pattern-inside: | + $SESSION = require('express-session'); + ... + - pattern: $SESSION(...) + - pattern-not-inside: $SESSION(<... {cookie:{secure:true}} ...>,...) + - pattern-not-inside: | + $OPTS = <... {cookie:{secure:true}} ...>; + ... + $SESSION($OPTS,...); + - pattern-not-inside: | + $OPTS = ...; + ... + $COOKIE = <... {secure:true} ...>; + ... + $SESSION($OPTS,...); + - pattern-not-inside: | + $OPTS = ...; + ... + $OPTS.cookie = <... {secure:true} ...>; + ... + $SESSION($OPTS,...); + - pattern-not-inside: | + $OPTS = ...; + ... + $COOKIE.secure = true; + ... + $SESSION($OPTS,...); + - pattern-not-inside: | + $OPTS = ...; + ... + $OPTS.cookie.secure = true; + ... + $SESSION($OPTS,...); +- id: javascript.express.security.audit.express-cookie-settings.express-cookie-session-no-httponly + message: >- + Default session middleware settings: `httpOnly` not set. + It ensures the cookie is sent only over HTTP(S), not client JavaScript, helping to protect against cross-site scripting attacks. + severity: WARNING + languages: [javascript, typescript] + metadata: + cwe: + - 'CWE-522: Insufficiently Protected Credentials' + owasp: + - A02:2017 - Broken Authentication + - A04:2021 - Insecure Design + source-rule-url: https://expressjs.com/en/advanced/best-practice-security.html + category: security + technology: + - express + cwe2021-top25: true + subcategory: + - vuln + likelihood: HIGH + impact: LOW + confidence: MEDIUM + references: + - https://owasp.org/Top10/A04_2021-Insecure_Design + patterns: + - pattern-either: + - pattern-inside: | + $SESSION = require('cookie-session'); + ... + - pattern-inside: | + $SESSION = require('express-session'); + ... + - pattern: $SESSION(...) + - pattern-not-inside: $SESSION(<... {cookie:{httpOnly:true}} ...>,...) + - pattern-not-inside: | + $OPTS = <... {cookie:{httpOnly:true}} ...>; + ... + $SESSION($OPTS,...); + - pattern-not-inside: | + $OPTS = ...; + ... + $COOKIE = <... {httpOnly:true} ...>; + ... + $SESSION($OPTS,...); + - pattern-not-inside: | + $OPTS = ...; + ... + $OPTS.cookie = <... {httpOnly:true} ...>; + ... + $SESSION($OPTS,...); + - pattern-not-inside: | + $OPTS = ...; + ... + $COOKIE.httpOnly = true; + ... + $SESSION($OPTS,...); + - pattern-not-inside: | + $OPTS = ...; + ... + $OPTS.cookie.httpOnly = true; + ... + $SESSION($OPTS,...); +- id: javascript.express.security.audit.express-cookie-settings.express-cookie-session-no-domain + message: >- + Default session middleware settings: `domain` not set. + It indicates the domain of the cookie; use it to compare against the domain of the server in which the URL is being requested. + If they match, then check the path attribute next. + severity: WARNING + languages: [javascript, typescript] + metadata: + cwe: + - 'CWE-522: Insufficiently Protected Credentials' + owasp: + - A02:2017 - Broken Authentication + - A04:2021 - Insecure Design + source-rule-url: https://expressjs.com/en/advanced/best-practice-security.html + category: security + technology: + - express + cwe2021-top25: true + subcategory: + - vuln + likelihood: HIGH + impact: LOW + confidence: MEDIUM + references: + - https://owasp.org/Top10/A04_2021-Insecure_Design + patterns: + - pattern-either: + - pattern-inside: | + $SESSION = require('cookie-session'); + ... + - pattern-inside: | + $SESSION = require('express-session'); + ... + - pattern: $SESSION(...) + - pattern-not-inside: $SESSION(<... {cookie:{domain:...}} ...>,...) + - pattern-not-inside: | + $OPTS = <... {cookie:{domain:...}} ...>; + ... + $SESSION($OPTS,...); + - pattern-not-inside: | + $OPTS = ...; + ... + $COOKIE = <... {domain:...} ...>; + ... + $SESSION($OPTS,...); + - pattern-not-inside: | + $OPTS = ...; + ... + $OPTS.cookie = <... {domain:...} ...>; + ... + $SESSION($OPTS,...); + - pattern-not-inside: | + $OPTS = ...; + ... + $COOKIE.domain = ...; + ... + $SESSION($OPTS,...); + - pattern-not-inside: | + $OPTS = ...; + ... + $OPTS.cookie.domain = ...; + ... + $SESSION($OPTS,...); +- id: javascript.express.security.audit.express-cookie-settings.express-cookie-session-no-path + message: >- + Default session middleware settings: `path` not set. + It indicates the path of the cookie; use it to compare against the request path. If this and domain match, then send the cookie in the request. + severity: WARNING + languages: [javascript, typescript] + metadata: + cwe: + - 'CWE-522: Insufficiently Protected Credentials' + owasp: + - A02:2017 - Broken Authentication + - A04:2021 - Insecure Design + source-rule-url: https://expressjs.com/en/advanced/best-practice-security.html + category: security + technology: + - express + cwe2021-top25: true + subcategory: + - vuln + likelihood: HIGH + impact: LOW + confidence: MEDIUM + references: + - https://owasp.org/Top10/A04_2021-Insecure_Design + patterns: + - pattern-either: + - pattern-inside: | + $SESSION = require('cookie-session'); + ... + - pattern-inside: | + $SESSION = require('express-session'); + ... + - pattern: $SESSION(...) + - pattern-not-inside: $SESSION(<... {cookie:{path:...}} ...>,...) + - pattern-not-inside: | + $OPTS = <... {cookie:{path:...}} ...>; + ... + $SESSION($OPTS,...); + - pattern-not-inside: | + $OPTS = ...; + ... + $COOKIE = <... {path:...} ...>; + ... + $SESSION($OPTS,...); + - pattern-not-inside: | + $OPTS = ...; + ... + $OPTS.cookie = <... {path:...} ...>; + ... + $SESSION($OPTS,...); + - pattern-not-inside: | + $OPTS = ...; + ... + $COOKIE.path = ...; + ... + $SESSION($OPTS,...); + - pattern-not-inside: | + $OPTS = ...; + ... + $OPTS.cookie.path = ...; + ... + $SESSION($OPTS,...); +- id: javascript.express.security.audit.express-cookie-settings.express-cookie-session-no-expires + message: >- + Default session middleware settings: `expires` not set. + Use it to set expiration date for persistent cookies. + severity: WARNING + languages: [javascript, typescript] + metadata: + cwe: + - 'CWE-522: Insufficiently Protected Credentials' + owasp: + - A02:2017 - Broken Authentication + - A04:2021 - Insecure Design + source-rule-url: https://expressjs.com/en/advanced/best-practice-security.html + category: security + technology: + - express + cwe2021-top25: true + subcategory: + - vuln + likelihood: HIGH + impact: LOW + confidence: MEDIUM + references: + - https://owasp.org/Top10/A04_2021-Insecure_Design + patterns: + - pattern-either: + - pattern-inside: | + $SESSION = require('cookie-session'); + ... + - pattern-inside: | + $SESSION = require('express-session'); + ... + - pattern: $SESSION(...) + - pattern-not-inside: $SESSION(<... {cookie:{expires:...}} ...>,...) + - pattern-not-inside: | + $OPTS = <... {cookie:{expires:...}} ...>; + ... + $SESSION($OPTS,...); + - pattern-not-inside: | + $OPTS = ...; + ... + $COOKIE = <... {expires:...} ...>; + ... + $SESSION($OPTS,...); + - pattern-not-inside: | + $OPTS = ...; + ... + $OPTS.cookie = <... {expires:...} ...>; + ... + $SESSION($OPTS,...); + - pattern-not-inside: | + $OPTS = ...; + ... + $COOKIE.expires = ...; + ... + $SESSION($OPTS,...); + - pattern-not-inside: |- + $OPTS = ...; + ... + $OPTS.cookie.expires = ...; + ... + $SESSION($OPTS,...); +- id: javascript.express.security.audit.express-detect-notevil-usage.express-detect-notevil-usage + message: >- + Detected usage of the `notevil` package, which is unmaintained and has vulnerabilities. + Using any sort of `eval()` functionality can be very dangerous, but if you must, + the `eval` package is an up to date alternative. Be sure that only trusted input + reaches an `eval()` function. + metadata: + category: security + references: + - https://github.com/mmckegg/notevil + cwe: + - 'CWE-1104: Use of Unmaintained Third Party Components' + owasp: + - A06:2021 - Vulnerable and Outdated Components + technology: + - javascript + - typescript + subcategory: + - audit + likelihood: LOW + impact: HIGH + confidence: LOW + languages: + - javascript + - typescript + severity: WARNING + patterns: + - pattern-either: + - pattern-inside: | + import $EVAL from 'notevil' + ... + - pattern-inside: | + import {$EVAL} from 'notevil' + ... + - pattern-inside: | + $EVAL = require('notevil') + ... + - pattern-either: + - patterns: + - pattern: $EVAL(...) + - pattern-not: $EVAL('...') + - patterns: + - pattern-either: + - pattern: $VM.runInContext("$CMD", ...) + - pattern: $VM.runInNewContext("$CMD", ...) + - pattern: $VM.runInThisContext("$CMD", ...) + - pattern: $VM.compileFunction("$CMD", ...) + - metavariable-pattern: + patterns: + - pattern: $EVAL(...) + - pattern-not: $EVAL('...') + metavariable: $CMD + language: typescript +- id: javascript.express.security.audit.express-jwt-not-revoked.express-jwt-not-revoked + message: >- + No token revoking configured for `express-jwt`. A leaked token could still be used and unable to be + revoked. + Consider using function as the `isRevoked` option. + metadata: + cwe: + - 'CWE-522: Insufficiently Protected Credentials' + owasp: + - A02:2017 - Broken Authentication + - A04:2021 - Insecure Design + source-rule-url: https://github.com/goldbergyoni/nodebestpractices/blob/master/sections/security/expirejwt.md + asvs: + section: 'V3: Session Management Verification Requirements' + control_id: 3.5.3 Insecue Stateless Session Tokens + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x12-V3-Session-management.md#v35-token-based-session-management + version: '4' + category: security + technology: + - express + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + references: + - https://owasp.org/Top10/A04_2021-Insecure_Design + languages: + - javascript + - typescript + severity: WARNING + patterns: + - pattern-inside: | + $JWT = require('express-jwt'); + ... + - pattern: $JWT(...) + - pattern-not-inside: $JWT(<... {isRevoked:...} ...>,...) + - pattern-not-inside: |- + $OPTS = <... {isRevoked:...} ...>; + ... + $JWT($OPTS,...); +- id: javascript.express.security.audit.express-libxml-noent.express-libxml-noent + message: >- + The libxml library processes user-input with the `noent` attribute is + set to `true` which can lead to being vulnerable to XML External Entities + (XXE) type attacks. It is recommended to set `noent` to `false` when using + this feature to ensure you are protected. + options: + interfile: true + metadata: + interfile: true + references: + - https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html + technology: + - express + category: security + cwe: + - 'CWE-611: Improper Restriction of XML External Entity Reference' + owasp: + - A04:2017 - XML External Entities (XXE) + - A05:2021 - Security Misconfiguration + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: HIGH + impact: HIGH + confidence: HIGH + languages: + - javascript + - typescript + severity: ERROR + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - pattern-inside: function ... ($REQ, $RES) {...} + - pattern-inside: function ... ($REQ, $RES, $NEXT) {...} + - patterns: + - pattern-either: + - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES) {...}) + - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES, $NEXT) {...}) + - metavariable-regex: + metavariable: $METHOD + regex: ^(get|post|put|head|delete|options)$ + - pattern-either: + - pattern: $REQ.query + - pattern: $REQ.body + - pattern: $REQ.params + - pattern: $REQ.cookies + - pattern: $REQ.headers + - pattern: $REQ.files.$ANYTHING.data.toString('utf8') + - pattern: $REQ.files.$ANYTHING['data'].toString('utf8') + - patterns: + - pattern-either: + - pattern-inside: | + ({ $REQ }: Request,$RES: Response, $NEXT: NextFunction) => + {...} + - pattern-inside: | + ({ $REQ }: Request,$RES: Response) => {...} + - focus-metavariable: $REQ + - pattern-either: + - pattern: params + - pattern: query + - pattern: cookies + - pattern: headers + - pattern: body + - pattern: files.$ANYTHING.data.toString('utf8') + - pattern: files.$ANYTHING['data'].toString('utf8') + pattern-sinks: + - pattern-either: + - patterns: + - pattern-either: + - pattern-inside: | + $XML = require('$IMPORT') + ... + - pattern-inside: | + import $XML from '$IMPORT' + ... + - pattern-inside: | + import * as $XML from '$IMPORT' + ... + - metavariable-regex: + metavariable: $IMPORT + regex: ^(libxmljs|libxmljs2)$ + - pattern-inside: $XML.$FUNC($QUERY, {...,noent:true,...}) + - metavariable-regex: + metavariable: $FUNC + regex: ^(parseXmlString|parseXml)$ + - focus-metavariable: $QUERY +- id: javascript.express.security.audit.express-libxml-vm-noent.express-libxml-vm-noent + message: Detected use of parseXml() function with the `noent` field set to `true`. This can lead to + an XML External Entities (XXE) attack if untrusted data is passed into it. + metadata: + references: + - https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html + owasp: + - A04:2017 - XML External Entities (XXE) + - A05:2021 - Security Misconfiguration + cwe: + - 'CWE-611: Improper Restriction of XML External Entity Reference' + category: security + technology: + - express + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH + confidence: LOW + languages: + - javascript + - typescript + severity: WARNING + patterns: + - pattern-either: + - patterns: + - pattern-either: + - pattern: $VM.runInContext("$CMD", ...) + - pattern: $VM.runInNewContext("$CMD", ...) + - pattern: $VM.runInThisContext("$CMD", ...) + - pattern: $VM.compileFunction("$CMD", ...) + - metavariable-pattern: + metavariable: $CMD + language: typescript + pattern-either: + - pattern: | + $LIBXML.parseXml($DATA, {..., noent: true, ...}, ...) + - patterns: + - pattern-inside: | + $OPTS = {..., noent: true, ...} + ... + - pattern: $LIBXML.parseXml( $DATA, $OPTS ) + - pattern: | + $LIBXML.parseXml($DATA, {..., noent: true, ...}, ...) + - patterns: + - pattern-inside: | + $OPTS = {..., noent: true, ...} + ... + - pattern: $LIBXML.parseXml( $DATA, $OPTS ) +- id: javascript.express.security.audit.express-open-redirect.express-open-redirect + message: >- + The application redirects to a URL specified by user-supplied input + `$REQ` that is not validated. This could redirect users to malicious + locations. Consider using an allow-list approach to validate URLs, or warn + users they are being redirected to a third-party website. + metadata: + technology: + - express + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html + cwe: + - "CWE-601: URL Redirection to Untrusted Site ('Open Redirect')" + category: security + owasp: + - A01:2021 - Broken Access Control + subcategory: + - vuln + likelihood: HIGH + impact: MEDIUM + confidence: HIGH + license: Commons Clause License Condition v1.0[LGPL-2.1-only] + languages: + - javascript + - typescript + severity: WARNING + options: + taint_unify_mvars: true + symbolic_propagation: true + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - pattern-inside: function ... ($REQ, $RES) {...} + - pattern-inside: function ... ($REQ, $RES, $NEXT) {...} + - patterns: + - pattern-either: + - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES) {...}) + - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES, $NEXT) {...}) + - metavariable-regex: + metavariable: $METHOD + regex: ^(get|post|put|head|delete|options)$ + - pattern-either: + - pattern: $REQ.query + - pattern: $REQ.body + - pattern: $REQ.params + - pattern: $REQ.cookies + - pattern: $REQ.headers + - patterns: + - pattern-either: + - pattern-inside: | + ({ $REQ }: Request,$RES: Response, $NEXT: NextFunction) => + {...} + - pattern-inside: | + ({ $REQ }: Request,$RES: Response) => {...} + - focus-metavariable: $REQ + - pattern-either: + - pattern: params + - pattern: query + - pattern: cookies + - pattern: headers + - pattern: body + pattern-sinks: + - patterns: + - pattern-either: + - pattern: $RES.redirect("$HTTP"+$REQ. ... .$VALUE) + - pattern: $RES.redirect("$HTTP"+$REQ. ... .$VALUE + $...A) + - pattern: $RES.redirect(`$HTTP${$REQ. ... .$VALUE}...`) + - pattern: $RES.redirect("$HTTP"+$REQ.$VALUE[...]) + - pattern: $RES.redirect("$HTTP"+$REQ.$VALUE[...] + $...A) + - pattern: $RES.redirect(`$HTTP${$REQ.$VALUE[...]}...`) + - metavariable-regex: + metavariable: $HTTP + regex: ^https?:\/\/$ + - pattern-either: + - pattern: $REQ. ... .$VALUE + - patterns: + - pattern-either: + - pattern: $RES.redirect($REQ. ... .$VALUE) + - pattern: $RES.redirect($REQ. ... .$VALUE + $...A) + - pattern: $RES.redirect(`${$REQ. ... .$VALUE}...`) + - pattern: $REQ. ... .$VALUE + - patterns: + - pattern-either: + - pattern: $RES.redirect($REQ.$VALUE['...']) + - pattern: $RES.redirect($REQ.$VALUE['...'] + $...A) + - pattern: $RES.redirect(`${$REQ.$VALUE['...']}...`) + - pattern: $REQ.$VALUE + - patterns: + - pattern-either: + - pattern-inside: | + $ASSIGN = $REQ. ... .$VALUE + ... + - pattern-inside: | + $ASSIGN = $REQ.$VALUE['...'] + ... + - pattern-inside: | + $ASSIGN = $REQ. ... .$VALUE + $...A + ... + - pattern-inside: | + $ASSIGN = $REQ.$VALUE['...'] + $...A + ... + - pattern-inside: | + $ASSIGN = `${$REQ. ... .$VALUE}...` + ... + - pattern-inside: | + $ASSIGN = `${$REQ.$VALUE['...']}...` + ... + - pattern-either: + - pattern: $RES.redirect($ASSIGN) + - pattern: $RES.redirect($ASSIGN + $...FOO) + - pattern: $RES.redirect(`${$ASSIGN}...`) + - focus-metavariable: $ASSIGN +- id: javascript.express.security.audit.express-path-join-resolve-traversal.express-path-join-resolve-traversal + message: >- + Possible writing outside of the destination, + make sure that the target path is nested in the intended destination + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - "CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')" + category: security + references: + - https://owasp.org/www-community/attacks/Path_Traversal + technology: + - express + - node.js + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: HIGH + impact: MEDIUM + confidence: MEDIUM + languages: + - javascript + - typescript + severity: WARNING + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - pattern-inside: function ... ($REQ, $RES) {...} + - pattern-inside: function ... ($REQ, $RES, $NEXT) {...} + - patterns: + - pattern-either: + - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES) {...}) + - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES, $NEXT) {...}) + - metavariable-regex: + metavariable: $METHOD + regex: ^(get|post|put|head|delete|options)$ + - pattern-either: + - pattern: $REQ.query + - pattern: $REQ.body + - pattern: $REQ.params + - pattern: $REQ.cookies + - pattern: $REQ.headers + - patterns: + - pattern-either: + - pattern-inside: | + ({ $REQ }: Request,$RES: Response, $NEXT: NextFunction) => + {...} + - pattern-inside: | + ({ $REQ }: Request,$RES: Response) => {...} + - focus-metavariable: $REQ + - pattern-either: + - pattern: params + - pattern: query + - pattern: cookies + - pattern: headers + - pattern: body + pattern-sinks: + - patterns: + - focus-metavariable: $SINK + - pattern-either: + - pattern-inside: | + $PATH = require('path'); + ... + - pattern-inside: | + import $PATH from 'path'; + ... + - pattern-either: + - pattern: $PATH.join(...,$SINK,...) + - pattern: $PATH.resolve(...,$SINK,...) + - patterns: + - focus-metavariable: $SINK + - pattern-inside: | + import 'path'; + ... + - pattern-either: + - pattern: path.join(...,$SINK,...) + - pattern: path.resolve(...,$SINK,...) + pattern-sanitizers: + - pattern: $Y.replace(...) + - pattern: $Y.indexOf(...) + - pattern: | + function ... (...) { + ... + <... $Y.indexOf(...) ...> + ... + } + - patterns: + - pattern: $FUNC(...) + - metavariable-regex: + metavariable: $FUNC + regex: sanitize +- id: javascript.express.security.audit.express-res-sendfile.express-res-sendfile + message: The application processes user-input, this is passed to res.sendFile which can allow an attacker + to arbitrarily read files on the system through path traversal. It is recommended to perform input + validation in addition to canonicalizing the path. This allows you to validate the path against the + intended directory it should be accessing. + metadata: + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Input_Validation_Cheat_Sheet.html + technology: + - express + category: security + cwe: + - 'CWE-73: External Control of File Name or Path' + owasp: + - A04:2021 - Insecure Design + subcategory: + - vuln + likelihood: HIGH + impact: MEDIUM + confidence: MEDIUM + languages: + - javascript + - typescript + severity: WARNING + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - pattern-inside: function ... ($REQ, $RES) {...} + - pattern-inside: function ... ($REQ, $RES, $NEXT) {...} + - patterns: + - pattern-either: + - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES) {...}) + - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES, $NEXT) {...}) + - metavariable-regex: + metavariable: $METHOD + regex: ^(get|post|put|head|delete|options)$ + - pattern-either: + - pattern: $REQ.query + - pattern: $REQ.body + - pattern: $REQ.params + - pattern: $REQ.cookies + - pattern: $REQ.headers + - patterns: + - pattern-either: + - pattern-inside: | + ({ $REQ }: Request,$RES: Response, $NEXT: NextFunction) => + {...} + - pattern-inside: | + ({ $REQ }: Request,$RES: Response) => {...} + - pattern-either: + - pattern: params + - pattern: query + - pattern: cookies + - pattern: headers + - pattern: body + - patterns: + - pattern-either: + - patterns: + - pattern-either: + - pattern-inside: | + function ... (...,$REQ: $TYPE, ...) {...} + - metavariable-regex: + metavariable: $TYPE + regex: ^(string|String) + pattern-sinks: + - patterns: + - pattern-either: + - pattern: $RES.$METH($QUERY,...) + - pattern-not-inside: $RES.$METH($QUERY,$OPTIONS) + - metavariable-regex: + metavariable: $METH + regex: ^(sendfile|sendFile)$ + - focus-metavariable: $QUERY +- id: javascript.express.security.audit.express-session-hardcoded-secret.express-session-hardcoded-secret + message: >- + A hard-coded credential was detected. It is not recommended to store credentials in source-code, + as this risks secrets + being leaked and used by either an internal or external malicious adversary. It is recommended to + use environment variables to securely provide credentials or retrieve credentials from a secure + vault or HSM (Hardware Security Module). + options: + interfile: true + metadata: + interfile: true + cwe: + - 'CWE-798: Use of Hard-coded Credentials' + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + owasp: + - A07:2021 - Identification and Authentication Failures + category: security + technology: + - express + - secrets + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: HIGH + impact: HIGH + confidence: HIGH + languages: + - javascript + - typescript + severity: WARNING + patterns: + - pattern-either: + - pattern-inside: | + $SESSION = require('express-session'); + ... + - pattern-inside: | + import $SESSION from 'express-session' + ... + - pattern-inside: | + import {..., $SESSION, ...} from 'express-session' + ... + - pattern-inside: | + import * as $SESSION from 'express-session' + ... + - patterns: + - pattern-either: + - pattern-inside: $APP.use($SESSION({...})) + - pattern: | + $SECRET = $VALUE + ... + $APP.use($SESSION($SECRET)) + - pattern: | + secret: '$Y' +- id: javascript.express.security.audit.express-ssrf.express-ssrf + message: >- + The following request $REQUEST.$METHOD() was found to be crafted from + user-input `$REQ` which can lead to Server-Side Request Forgery (SSRF) + vulnerabilities. It is recommended where possible to not allow user-input + to craft the base request, but to be treated as part of the path or query + parameter. When user-input is necessary to craft the request, it is + recommeneded to follow OWASP best practices to prevent abuse. + metadata: + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet.html + cwe: + - "CWE-918: Server-Side Request Forgery (SSRF)" + technology: + - express + category: security + owasp: + - A10:2021 - Server-Side Request Forgery (SSRF) + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: HIGH + confidence: MEDIUM + languages: + - javascript + - typescript + severity: WARNING + mode: taint + options: + taint_unify_mvars: true + pattern-sources: + - patterns: + - pattern-either: + - pattern-inside: function ... ($REQ, ...) {...} + - pattern-either: + - pattern: $REQ.query + - pattern: $REQ.body + - pattern: $REQ.params + - pattern: $REQ.cookies + - pattern: $REQ.headers + - patterns: + - pattern-either: + - pattern-inside: | + ({ $REQ }: Request,...) => + {...} + - pattern-inside: | + ({ $REQ }: $EXPRESS.Request,...) => {...} + - focus-metavariable: $REQ + - pattern-either: + - pattern: params + - pattern: query + - pattern: cookies + - pattern: headers + - pattern: body + # we have a deepsemgrep rule which will make this 10x smaller. + pattern-sinks: + - patterns: + - pattern-either: + - pattern-inside: | + $REQUEST = require('request') + ... + - pattern-inside: | + import * as $REQUEST from 'request' + ... + - pattern-inside: | + import $REQUEST from 'request' + ... + # Direct usage with http:// https:// and // + - pattern-either: + - pattern: $REQUEST.$METHOD("$HTTP"+$REQ. ... .$VALUE) + - pattern: $REQUEST.$METHOD("$HTTP"+$REQ. ... .$VALUE + $...A) + - pattern: $REQUEST.$METHOD(`$HTTP${$REQ. ... .$VALUE}...`) + - pattern: $REQUEST.$METHOD("$HTTP"+$REQ.$VALUE[...]) + - pattern: $REQUEST.$METHOD("$HTTP"+$REQ.$VALUE[...] + $...A) + - pattern: $REQUEST.$METHOD(`$HTTP${$REQ.$VALUE[...]}...`) + - metavariable-regex: + metavariable: $METHOD + regex: ^(get|post|put|patch|del|head|delete)$ + - metavariable-regex: + metavariable: $HTTP + regex: ^(https?:\/\/|//)$ + - pattern-either: + - pattern: $REQ. ... .$VALUE + - patterns: + - pattern-either: + - pattern-inside: | + $REQUEST = require('request') + ... + - pattern-inside: | + import * as $REQUEST from 'request' + ... + - pattern-inside: | + import $REQUEST from 'request' + ... + # Direct usage with req.body at start + - pattern-either: + - pattern: $REQUEST.$METHOD($REQ. ... .$VALUE,...) + - pattern: $REQUEST.$METHOD($REQ. ... .$VALUE + $...A,...) + - pattern: $REQUEST.$METHOD(`${$REQ. ... .$VALUE}...`,...) + - pattern: $REQ. ... .$VALUE + - metavariable-regex: + metavariable: $METHOD + regex: ^(get|post|put|patch|del|head|delete)$ + - patterns: + - pattern-either: + - pattern-inside: | + $REQUEST = require('request') + ... + - pattern-inside: | + import * as $REQUEST from 'request' + ... + - pattern-inside: | + import $REQUEST from 'request' + ... + # Direct usage with req.body['value'] at start + - pattern-either: + - pattern: $REQUEST.$METHOD($REQ.$VALUE['...'],...) + - pattern: $REQUEST.$METHOD($REQ.$VALUE['...'] + $...A,...) + - pattern: $REQUEST.$METHOD(`${$REQ.$VALUE['...']}...`,...) + - pattern: $REQ.$VALUE + - metavariable-regex: + metavariable: $METHOD + regex: ^(get|post|put|patch|del|head|delete)$ + - patterns: + - pattern-either: + - pattern-inside: | + $REQUEST = require('request') + ... + - pattern-inside: | + import * as $REQUEST from 'request' + ... + - pattern-inside: | + import $REQUEST from 'request' + ... + # Direct usage with req.body from assign + - pattern-either: + - pattern-inside: | + $ASSIGN = $REQ. ... .$VALUE + ... + - pattern-inside: | + $ASSIGN = $REQ. ... .$VALUE['...'] + ... + - pattern-inside: | + $ASSIGN = $REQ. ... .$VALUE + $...A + ... + - pattern-inside: | + $ASSIGN = $REQ. ... .$VALUE['...'] + $...A + ... + - pattern-inside: | + $ASSIGN = `${$REQ. ... .$VALUE}...` + ... + - pattern-inside: | + $ASSIGN = `${$REQ. ... .$VALUE['...']}...` + ... + # Direct usage with req.body with http|https|// from assign + - patterns: + - pattern-either: + - pattern-inside: | + $ASSIGN = "$HTTP"+ $REQ. ... .$VALUE + ... + - pattern-inside: | + $ASSIGN = "$HTTP"+$REQ. ... .$VALUE + $...A + ... + - pattern-inside: | + $ASSIGN = "$HTTP"+$REQ.$VALUE[...] + ... + - pattern-inside: | + $ASSIGN = "$HTTP"+$REQ.$VALUE[...] + $...A + ... + - pattern-inside: | + $ASSIGN = `$HTTP${$REQ.$VALUE[...]}...` + ... + - metavariable-regex: + metavariable: $HTTP + regex: ^(https?:\/\/|//)$ + - pattern-either: + - pattern: $REQUEST.$METHOD($ASSIGN,...) + - pattern: $REQUEST.$METHOD($ASSIGN + $...FOO,...) + - pattern: $REQUEST.$METHOD(`${$ASSIGN}...`,...) + - patterns: + - pattern-either: + - pattern: $REQUEST.$METHOD("$HTTP"+$ASSIGN,...) + - pattern: $REQUEST.$METHOD("$HTTP"+$ASSIGN + $...A,...) + - pattern: $REQUEST.$METHOD(`$HTTP${$ASSIGN}...`,...) + - metavariable-regex: + metavariable: $HTTP + regex: ^(https?:\/\/|//)$ + - pattern: $ASSIGN + - metavariable-regex: + metavariable: $METHOD + regex: ^(get|post|put|patch|del|head|delete)$ +- id: javascript.express.security.audit.express-third-party-object-deserialization.express-third-party-object-deserialization + message: The following function call $SER.$FUNC accepts user controlled data which can result in Remote + Code Execution (RCE) through Object Deserialization. It is recommended to use secure data processing + alternatives such as JSON.parse() and Buffer.from(). + options: + interfile: true + metadata: + interfile: true + technology: + - express + category: security + cwe: + - 'CWE-502: Deserialization of Untrusted Data' + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html + source_rule_url: + - https://github.com/ajinabraham/njsscan/blob/75bfbeb9c8d72999e4d527dfa2548f7f0f3cc48a/njsscan/rules/semantic_grep/eval/eval_deserialize.yaml + owasp: + - A08:2017 - Insecure Deserialization + - A08:2021 - Software and Data Integrity Failures + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: HIGH + impact: HIGH + confidence: HIGH + languages: + - javascript + - typescript + severity: WARNING + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - pattern-inside: function ... ($REQ, $RES) {...} + - pattern-inside: function ... ($REQ, $RES, $NEXT) {...} + - patterns: + - pattern-either: + - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES) {...}) + - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES, $NEXT) {...}) + - metavariable-regex: + metavariable: $METHOD + regex: ^(get|post|put|head|delete|options)$ + - pattern-either: + - pattern: $REQ.query + - pattern: $REQ.body + - pattern: $REQ.params + - pattern: $REQ.cookies + - pattern: $REQ.headers + - pattern: $REQ.files.$ANYTHING.data.toString('utf8') + - pattern: $REQ.files.$ANYTHING['data'].toString('utf8') + - patterns: + - pattern-either: + - pattern-inside: | + ({ $REQ }: Request,$RES: Response, $NEXT: NextFunction) => + {...} + - pattern-inside: | + ({ $REQ }: Request,$RES: Response) => {...} + - focus-metavariable: $REQ + - pattern-either: + - pattern: params + - pattern: query + - pattern: cookies + - pattern: headers + - pattern: body + - pattern: files.$ANYTHING.data.toString('utf8') + - pattern: files.$ANYTHING['data'].toString('utf8') + pattern-sinks: + - pattern-either: + - patterns: + - pattern-either: + - pattern-inside: | + $SER = require('$IMPORT') + ... + - pattern-inside: | + import $SER from '$IMPORT' + ... + - pattern-inside: | + import * as $SER from '$IMPORT' + ... + - metavariable-regex: + metavariable: $IMPORT + regex: ^(node-serialize|serialize-to-js)$ + - pattern: $SER.$FUNC(...) + - metavariable-regex: + metavariable: $FUNC + regex: ^(unserialize|deserialize)$ +- id: javascript.express.security.audit.express-xml2json-xxe-event.express-xml2json-xxe-event + message: >- + Xml Parser is used inside Request Event. + Make sure that unverified user data can not reach the XML Parser, + as it can result in XML External or Internal Entity (XXE) Processing vulnerabilities + metadata: + owasp: + - A04:2017 - XML External Entities (XXE) + - A05:2021 - Security Misconfiguration + cwe: + - 'CWE-611: Improper Restriction of XML External Entity Reference' + category: security + technology: + - express + references: + - https://www.npmjs.com/package/xml2json + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: HIGH + confidence: MEDIUM + languages: + - javascript + - typescript + severity: WARNING + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - pattern-inside: function ... ($REQ, $RES) {...} + - pattern-inside: function ... ($REQ, $RES, $NEXT) {...} + - patterns: + - pattern-either: + - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES) {...}) + - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES, $NEXT) {...}) + - metavariable-regex: + metavariable: $METHOD + regex: ^(get|post|put|head|delete|options)$ + - pattern-either: + - pattern: $REQ.query + - pattern: $REQ.body + - pattern: $REQ.params + - pattern: $REQ.cookies + - pattern: $REQ.headers + - patterns: + - pattern-either: + - pattern-inside: > + ({ $REQ }: Request,$RES: Response, $NEXT: NextFunction) => + {...} + - pattern-inside: | + ({ $REQ }: Request,$RES: Response) => {...} + - focus-metavariable: $REQ + - pattern-either: + - pattern: params + - pattern: query + - pattern: cookies + - pattern: headers + - pattern: body + pattern-sinks: + - patterns: + - pattern-either: + - pattern-inside: | + require('xml2json'); + ... + - pattern-inside: | + import 'xml2json'; + ... + - pattern: $REQ.on('...', function(...) { ... $EXPAT.toJson($INPUT,...); ... }) +- id: javascript.express.security.audit.possible-user-input-redirect.unknown-value-in-redirect + message: >- + It looks like '$UNK' is read from user input and it is used to as a redirect. Ensure + '$UNK' is not externally controlled, otherwise this is an open redirect. + metadata: + owasp: + - A01:2021 - Broken Access Control + cwe: + - "CWE-601: URL Redirection to Untrusted Site ('Open Redirect')" + asvs: + section: V5 Validation, Sanitization and Encoding + control_id: 5.5.1 Insecue Redirect + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x13-V5-Validation-Sanitization-Encoding.md#v51-input-validation + version: '4' + category: security + technology: + - express + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + languages: + - javascript + - typescript + severity: WARNING + patterns: + - pattern-either: + - pattern-inside: | + $UNK = query.$B; + ... + - pattern-inside: | + $UNK = $A.query.$B; + ... + - pattern-inside: | + $UNK = req.$SOMETHING; + ... + - pattern: $RES.redirect(..., <... $UNK ...>, ...) +- id: javascript.express.security.audit.remote-property-injection.remote-property-injection + message: >- + Bracket object notation with user input is present, this might allow an + attacker to access all properties of the object and even it's prototype. Use + literal values for object properties. + metadata: + confidence: LOW + owasp: + - A02:2017 - Broken Authentication + - A04:2021 - Insecure Design + cwe: + - 'CWE-522: Insufficiently Protected Credentials' + category: security + technology: + - express + references: + - https://github.com/nodesecurity/eslint-plugin-security/blob/3c7522ca1be800353513282867a1034c795d9eb4/docs/the-dangers-of-square-bracket-notation.md + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + languages: + - javascript + - typescript + severity: ERROR + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - pattern-inside: function ... ($REQ, $RES) {...} + - pattern-inside: function ... ($REQ, $RES, $NEXT) {...} + - patterns: + - pattern-either: + - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES) {...}) + - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES, $NEXT) {...}) + - metavariable-regex: + metavariable: $METHOD + regex: ^(get|post|put|head|delete|options)$ + - pattern-either: + - pattern: $REQ.query + - pattern: $REQ.body + - pattern: $REQ.params + - pattern: $REQ.cookies + - pattern: $REQ.headers + - patterns: + - pattern-either: + - pattern-inside: | + ({ $REQ }: Request,$RES: Response, $NEXT: NextFunction) => + {...} + - pattern-inside: | + ({ $REQ }: Request,$RES: Response) => {...} + - focus-metavariable: $REQ + - pattern-either: + - pattern: params + - pattern: query + - pattern: cookies + - pattern: headers + - pattern: body + pattern-sinks: + - patterns: + - pattern-inside: $OBJ[...] = ... + - pattern-not-inside: $OBJ["..."] = ... + - pattern-not-inside: $OBJ[...] = "..." + - pattern: $INDEX + - pattern-not: | + "..." + $INDEX + - pattern-not: | + $INDEX + "..." + pattern-sanitizers: + - patterns: + - pattern: var $X = ... + - pattern-not: var $X = $REQ.$ANY +- id: javascript.express.security.audit.res-render-injection.res-render-injection + message: >- + User controllable data `$REQ` enters `$RES.render(...)` this can lead to the loading + of other HTML/templating pages that they may not be authorized to render. An attacker + may attempt to use directory traversal techniques e.g. `../folder/index` to access other + HTML pages on the file system. Where possible, do not allow users to define what should be + loaded in $RES.render or use an allow list for the existing application. + options: + interfile: true + metadata: + interfile: true + owasp: + - A01:2021 - Broken Access Control + cwe: + - 'CWE-706: Use of Incorrectly-Resolved Name or Reference' + category: security + technology: + - express + references: + - http://expressjs.com/en/4x/api.html#res.render + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + languages: + - javascript + - typescript + severity: WARNING + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - pattern-inside: function ... ($REQ, $RES) {...} + - pattern-inside: function ... ($REQ, $RES, $NEXT) {...} + - patterns: + - pattern-either: + - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES) {...}) + - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES, $NEXT) {...}) + - metavariable-regex: + metavariable: $METHOD + regex: ^(get|post|put|head|delete|options)$ + - pattern-either: + - pattern: $REQ.query + - pattern: $REQ.body + - pattern: $REQ.params + - pattern: $REQ.cookies + - pattern: $REQ.headers + - patterns: + - pattern-either: + - pattern-inside: | + ({ $REQ }: Request,$RES: Response, $NEXT: NextFunction) => + {...} + - pattern-inside: | + ({ $REQ }: Request,$RES: Response) => {...} + - focus-metavariable: $REQ + - pattern-either: + - pattern: params + - pattern: query + - pattern: cookies + - pattern: headers + - pattern: body + pattern-sinks: + - patterns: + - pattern-either: + - pattern: $RES.render($SINK, ...) + - focus-metavariable: $SINK +- id: javascript.express.security.audit.xss.direct-response-write.direct-response-write + message: >- + Detected directly writing to a Response object from user-defined input. + This bypasses any HTML escaping and may expose your application to a Cross-Site-scripting + (XSS) vulnerability. Instead, use 'resp.render()' to render safely escaped HTML. + options: + interfile: true + metadata: + interfile: true + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + cwe: + - 'CWE-79: Improper Neutralization of Input During Web Page Generation (''Cross-site + Scripting'')' + category: security + technology: + - express + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + license: Commons Clause License Condition v1.0[LGPL-2.1-only] + vulnerability_class: + - Cross-Site-Scripting (XSS) + languages: + - javascript + - typescript + severity: WARNING + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - pattern-inside: function ... ($REQ, $RES) {...} + - pattern-inside: function ... ($REQ, $RES, $NEXT) {...} + - patterns: + - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES) {...}) + - metavariable-regex: + metavariable: $METHOD + regex: ^(get|post|put|head|delete|options) + - pattern-not-inside: | + function ... ($REQ, $RES) { + ... + $RES.$SET('Content-Type', '$TYPE') + } + - pattern-not-inside: | + $APP.$METHOD(..., function $FUNC($REQ, $RES) { + ... + $RES.$SET('Content-Type', '$TYPE') + }) + - pattern-not-inside: | + function ... ($REQ, $RES, $NEXT) { + ... + $RES.$SET('Content-Type', '$TYPE') + } + - pattern-not-inside: | + function ... ($REQ, $RES) { + ... + $RES.set('$TYPE') + } + - pattern-not-inside: | + $APP.$METHOD(..., function $FUNC($REQ, $RES) { + ... + $RES.set('$TYPE') + }) + - pattern-not-inside: | + function ... ($REQ, $RES, $NEXT) { + ... + $RES.set('$TYPE') + } + - pattern-either: + - pattern: $REQ.query + - pattern: $REQ.body + - pattern: $REQ.params + - patterns: + - pattern-either: + - pattern-inside: | + ({ $REQ }: Request,$RES: Response, $NEXT: NextFunction) => + {...} + - pattern-inside: | + ({ $REQ }: Request,$RES: Response) => {...} + - pattern-not-inside: | + ({ $REQ }: Request,$RES: Response, $NEXT: NextFunction) => + { + ... + $RES.$SET('Content-Type', '$TYPE') + } + - pattern-not-inside: | + ({ $REQ }: Request,$RES: Response) => { + ... + $RES.$SET('Content-Type', '$TYPE') + } + - pattern-not-inside: | + ({ $REQ }: Request,$RES: Response, $NEXT: NextFunction) => + { + ... + $RES.set('$TYPE') + } + - focus-metavariable: $REQ + - pattern-either: + - pattern: params + - pattern: query + - pattern: body + pattern-sinks: + - patterns: + - pattern-inside: function ... (..., $RES,...) {...} + - pattern-either: + - pattern: $RES.write($ARG) + - pattern: $RES.send($ARG) + - pattern-not: $RES. ... .set('...'). ... .send($ARG) + - pattern-not: $RES. ... .type('...'). ... .send($ARG) + - pattern-not-inside: $RES.$METHOD({ ... }) + - focus-metavariable: $ARG + pattern-sanitizers: + - patterns: + - pattern-either: + - pattern-inside: | + import $S from "underscore.string" + ... + - pattern-inside: | + import * as $S from "underscore.string" + ... + - pattern-inside: | + import $S from "underscore.string" + ... + - pattern-inside: | + $S = require("underscore.string") + ... + - pattern-either: + - pattern: $S.escapeHTML(...) + - patterns: + - pattern-either: + - pattern-inside: | + import $S from "dompurify" + ... + - pattern-inside: | + import { ..., $S,... } from "dompurify" + ... + - pattern-inside: | + import * as $S from "dompurify" + ... + - pattern-inside: | + $S = require("dompurify") + ... + - pattern-inside: | + import $S from "isomorphic-dompurify" + ... + - pattern-inside: | + import * as $S from "isomorphic-dompurify" + ... + - pattern-inside: | + $S = require("isomorphic-dompurify") + ... + - pattern-either: + - patterns: + - pattern-inside: | + $VALUE = $S(...) + ... + - pattern: $VALUE.sanitize(...) + - patterns: + - pattern-inside: | + $VALUE = $S.sanitize + ... + - pattern: $S(...) + - pattern: $S.sanitize(...) + - pattern: $S(...) + - patterns: + - pattern-either: + - pattern-inside: | + import $S from 'xss'; + ... + - pattern-inside: | + import * as $S from 'xss'; + ... + - pattern-inside: | + $S = require("xss") + ... + - pattern: $S(...) + - patterns: + - pattern-either: + - pattern-inside: | + import $S from 'sanitize-html'; + ... + - pattern-inside: | + import * as $S from "sanitize-html"; + ... + - pattern-inside: | + $S = require("sanitize-html") + ... + - pattern: $S(...) + - patterns: + - pattern-either: + - pattern-inside: | + $S = new Remarkable() + ... + - pattern: $S.render(...) + - patterns: + - pattern-either: + - pattern-inside: | + import $S from 'express-xss-sanitizer'; + ... + - pattern-inside: | + import * as $S from "express-xss-sanitizer"; + ... + - pattern-inside: | + const { ..., $S, ... } = require('express-xss-sanitizer'); + ... + - pattern-inside: | + var { ..., $S, ... } = require('express-xss-sanitizer'); + ... + - pattern-inside: | + let { ...,$S,... } = require('express-xss-sanitizer'); + ... + - pattern-inside: | + $S = require("express-xss-sanitizer") + ... + - pattern: $S(...) + - patterns: + - pattern: $RES. ... .type('$F'). ... .send(...) + - metavariable-regex: + metavariable: $F + regex: (?!.*text/html) + - patterns: + - pattern-inside: | + $X = [...]; + ... + - pattern: | + if(<... !$X.includes($SOURCE)...>) { + ... + return ... + } + ... + - pattern: $SOURCE +- id: javascript.express.security.audit.xss.ejs.explicit-unescape.template-explicit-unescape + message: >- + Detected an explicit unescape in an EJS template, using + '<%- ... %>' If external data can reach these locations, + your application is exposed to a cross-site scripting (XSS) + vulnerability. Use '<%= ... %>' to escape this data. If you + need escaping, ensure no external data can reach this location. + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + references: + - http://www.managerjs.com/blog/2015/05/will-ejs-escape-save-me-from-xss-sorta/ + category: security + technology: + - express + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + languages: + - regex + severity: WARNING + paths: + include: + - '*.ejs' + - '*.html' + pattern-regex: <%-((?!include).)*?%> + fix-regex: + regex: <%-(.*?)%> + replacement: <%=\1%> +- id: javascript.express.security.audit.xss.ejs.var-in-href.var-in-href + message: >- + Detected a template variable used in an anchor tag with + the 'href' attribute. This allows a malicious actor to + input the 'javascript:' URI and is subject to cross- + site scripting (XSS) attacks. If using a relative URL, + start with a literal forward slash and concatenate the URL, + like this: href='/<%= link %>'. You may also consider setting + the Content Security Policy (CSP) header. + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + references: + - https://flask.palletsprojects.com/en/1.1.x/security/#cross-site-scripting-xss#:~:text=javascript:%20URI + - https://github.com/pugjs/pug/issues/2952 + category: security + technology: + - express + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + languages: + - regex + severity: WARNING + paths: + include: + - '*.ejs' + - '*.html' + pattern-regex: ]*?[^\/&=]<%.*?%>.*?> +- id: javascript.express.security.audit.xss.ejs.var-in-script-src.var-in-script-src + message: >- + Detected a template variable used as the 'src' in a script tag. + Although template variables are HTML escaped, HTML + escaping does not always prevent malicious URLs from being injected + and could results in a cross-site scripting (XSS) vulnerability. + Prefer not to dynamically generate the 'src' attribute and use static + URLs instead. If you must do this, carefully check URLs against an + allowlist and be sure to URL-encode the result. + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + references: + - https://www.veracode.com/blog/secure-development/nodejs-template-engines-why-default-encoders-are-not-enough + - https://github.com/ESAPI/owasp-esapi-js + category: security + technology: + - express + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + languages: + - generic + severity: WARNING + patterns: + - pattern-inside: + - pattern-not-inside: + - pattern: '{{ ... }}' + paths: + include: + - '*.mustache' + - '*.hbs' + - '*.html' +- id: javascript.express.security.audit.xss.pug.and-attributes.template-and-attributes + message: >- + Detected a unescaped variables using '&attributes'. + If external data can reach these locations, + your application is exposed to a cross-site scripting (XSS) + vulnerability. If you must do this, ensure no external data + can reach this location. + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + references: + - https://pugjs.org/language/attributes.html#attributes + category: security + technology: + - express + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + languages: + - regex + severity: WARNING + paths: + include: + - '*.pug' + pattern-regex: .*&attributes.* +- id: javascript.express.security.audit.xss.pug.explicit-unescape.template-explicit-unescape + message: >- + Detected an explicit unescape in a Pug template, using either + '!=' or '!{...}'. If external data can reach these locations, + your application is exposed to a cross-site scripting (XSS) + vulnerability. If you must do this, ensure no external data + can reach this location. + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + references: + - https://pugjs.org/language/code.html#unescaped-buffered-code + - https://pugjs.org/language/attributes.html#unescaped-attributes + category: security + technology: + - express + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + languages: + - regex + severity: WARNING + paths: + include: + - '*.pug' + pattern-either: + - pattern-regex: \w.*(!=)[^=].* + - pattern-regex: '!{.*?}' +- id: javascript.express.security.audit.xss.pug.var-in-href.var-in-href + message: >- + Detected a template variable used in an anchor tag with + the 'href' attribute. This allows a malicious actor to + input the 'javascript:' URI and is subject to cross- + site scripting (XSS) attacks. If using a relative URL, + start with a literal forward slash and concatenate the URL, + like this: a(href='/'+url). You may also consider setting + the Content Security Policy (CSP) header. + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + references: + - https://github.com/pugjs/pug/issues/2952 + - https://flask.palletsprojects.com/en/1.1.x/security/#cross-site-scripting-xss#:~:text=javascript:%20URI + category: security + technology: + - express + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + languages: + - regex + severity: WARNING + paths: + include: + - '*.pug' + pattern-regex: a\(.*href=[^'"].*\) +- id: javascript.express.security.audit.xss.pug.var-in-script-tag.var-in-script-tag + message: >- + Detected a template variable used in a script tag. + Although template variables are HTML escaped, HTML + escaping does not always prevent cross-site scripting (XSS) + attacks when used directly in JavaScript. If you need this + data on the rendered page, consider placing it in the HTML + portion (outside of a script tag). Alternatively, use a + JavaScript-specific encoder, such as the one available + in OWASP ESAPI. + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + references: + - https://www.veracode.com/blog/secure-development/nodejs-template-engines-why-default-encoders-are-not-enough + - https://github.com/ESAPI/owasp-esapi-js + category: security + technology: + - express + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + languages: + - regex + severity: WARNING + paths: + include: + - '*.pug' + pattern-either: + - pattern-regex: script\s*=[A-Za-z0-9]+ + - pattern-regex: script\s*=.*["']\s*\+.* + - pattern-regex: script\s*=[^'"]+\+.* + - pattern-regex: script\(.*?\)\s*=\s*[A-Za-z0-9]+ + - pattern-regex: script\(.*?\)\s*=\s*.*["']\s*\+.* + - pattern-regex: script\(.*?\)\s*=\s*[^'"]+\+.* +- id: javascript.express.security.cors-misconfiguration.cors-misconfiguration + message: >- + By letting user input control CORS parameters, there is a risk that software does not properly verify + that the source + of data or communication is valid. Use literal values for CORS settings. + metadata: + owasp: + - A07:2021 - Identification and Authentication Failures + cwe: + - 'CWE-346: Origin Validation Error' + category: security + references: + - https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS + technology: + - express + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + languages: + - javascript + - typescript + severity: WARNING + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - pattern-inside: function ... ($REQ, $RES) {...} + - pattern-inside: function ... ($REQ, $RES, $NEXT) {...} + - patterns: + - pattern-either: + - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES) {...}) + - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES, $NEXT) {...}) + - metavariable-regex: + metavariable: $METHOD + regex: ^(get|post|put|head|delete|options)$ + - pattern-either: + - pattern: $REQ.query + - pattern: $REQ.body + - pattern: $REQ.params + - pattern: $REQ.cookies + - pattern: $REQ.headers + - patterns: + - pattern-either: + - pattern-inside: | + ({ $REQ }: Request,$RES: Response, $NEXT: NextFunction) => + {...} + - pattern-inside: | + ({ $REQ }: Request,$RES: Response) => {...} + - focus-metavariable: $REQ + - pattern-either: + - pattern: params + - pattern: query + - pattern: cookies + - pattern: headers + - pattern: body + pattern-sinks: + - patterns: + - pattern-either: + - pattern: $RES.set($HEADER, $X) + - pattern: $RES.header($HEADER, $X) + - pattern: $RES.setHeader($HEADER, $X) + - pattern: | + $RES.set({$HEADER: $X}, ...) + - pattern: | + $RES.writeHead($STATUS, {$HEADER: $X}, ...) + - focus-metavariable: $X + - metavariable-regex: + metavariable: $HEADER + regex: .*(Access-Control-Allow-Origin|access-control-allow-origin).* +- id: javascript.express.security.express-data-exfiltration.express-data-exfiltration + message: >- + Depending on the context, user control data in `Object.assign` can cause web response to include data + that it should not have or can lead to a mass assignment vulnerability. + metadata: + owasp: + - A08:2021 - Software and Data Integrity Failures + cwe: + - 'CWE-915: Improperly Controlled Modification of Dynamically-Determined Object Attributes' + references: + - https://en.wikipedia.org/wiki/Mass_assignment_vulnerability + - https://cheatsheetseries.owasp.org/cheatsheets/Mass_Assignment_Cheat_Sheet.html + category: security + technology: + - express + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + languages: + - javascript + - typescript + severity: WARNING + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - pattern-inside: function ... ($REQ, $RES) {...} + - pattern-inside: function ... ($REQ, $RES, $NEXT) {...} + - patterns: + - pattern-either: + - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES) {...}) + - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES, $NEXT) {...}) + - metavariable-regex: + metavariable: $METHOD + regex: ^(get|post|put|head|delete|options)$ + - pattern-either: + - pattern: $REQ.query + - pattern: $REQ.body + - pattern: $REQ.params + - pattern: $REQ.cookies + - pattern: $REQ.headers + - patterns: + - pattern-either: + - pattern-inside: | + ({ $REQ }: Request,$RES: Response, $NEXT: NextFunction) => + {...} + - pattern-inside: | + ({ $REQ }: Request,$RES: Response) => {...} + - focus-metavariable: $REQ + - pattern-either: + - pattern: params + - pattern: query + - pattern: cookies + - pattern: headers + - pattern: body + pattern-sinks: + - pattern: Object.assign(...) +- id: javascript.express.security.express-expat-xxe.express-expat-xxe + message: >- + Make sure that unverified user data can not reach the XML Parser, as it + can result in XML External or Internal Entity (XXE) Processing + vulnerabilities. + options: + interfile: true + metadata: + interfile: true + owasp: + - A04:2017 - XML External Entities (XXE) + - A05:2021 - Security Misconfiguration + cwe: + - 'CWE-611: Improper Restriction of XML External Entity Reference' + asvs: + section: V5 Validation, Sanitization and Encoding + control_id: 5.5.2 Insecue XML Deserialization + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x13-V5-Validation-Sanitization-Encoding.md#v55-deserialization-prevention + version: '4' + references: + - https://github.com/astro/node-expat + category: security + technology: + - express + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + languages: + - javascript + - typescript + severity: ERROR + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - pattern-inside: function ... ($REQ, $RES) {...} + - pattern-inside: function ... ($REQ, $RES, $NEXT) {...} + - patterns: + - pattern-either: + - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES) {...}) + - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES, $NEXT) {...}) + - metavariable-regex: + metavariable: $METHOD + regex: ^(get|post|put|head|delete|options)$ + - pattern-either: + - pattern: $REQ.query + - pattern: $REQ.body + - pattern: $REQ.params + - pattern: $REQ.cookies + - pattern: $REQ.headers + - patterns: + - pattern-either: + - pattern-inside: | + ({ $REQ }: Request,$RES: Response, $NEXT: NextFunction) => + {...} + - pattern-inside: | + ({ $REQ }: Request,$RES: Response) => {...} + - focus-metavariable: $REQ + - pattern-either: + - pattern: params + - pattern: query + - pattern: cookies + - pattern: headers + - pattern: body + pattern-sinks: + - patterns: + - pattern-either: + - pattern-inside: | + $XML = require('node-expat') + ... + - pattern-inside: | + import $XML from 'node-expat' + ... + - pattern-inside: | + import * as $XML from 'node-expat' + ... + - pattern-either: + - pattern-inside: | + $PARSER = new $XML.Parser(...); + ... + - pattern-either: + - pattern: $PARSER.parse($QUERY) + - pattern: $PARSER.write($QUERY) + - focus-metavariable: $QUERY +- id: javascript.express.security.express-insecure-template-usage.express-insecure-template-usage + message: User data from `$REQ` is being compiled into the template, which can lead to a Server Side + Template Injection (SSTI) vulnerability. + options: + interfile: true + metadata: + interfile: true + category: security + cwe: + - 'CWE-1336: Improper Neutralization of Special Elements Used in a Template Engine' + owasp: + - A03:2021 - Injection + - A01:2017 - Injection + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Injection_Prevention_Cheat_Sheet.html + technology: + - javascript + - typescript + - express + - pug + - jade + - dot + - ejs + - nunjucks + - lodash + - handlbars + - mustache + - hogan.js + - eta + - squirrelly + source_rule_url: + - https://github.com/github/codeql/blob/2ba2642c7ab29b9eedef33bcc2b8cd1d203d0c10/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/template-sinks.js + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + languages: + - javascript + - typescript + severity: WARNING + mode: taint + pattern-propagators: + - pattern: $MODEL.$FIND($E).then((...,$S,...)=>{...}) + from: $E + to: $S + pattern-sources: + - patterns: + - pattern-either: + - pattern-inside: function ... ($REQ, $RES) {...} + - pattern-inside: function ... ($REQ, $RES, $NEXT) {...} + - patterns: + - pattern-either: + - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES) {...}) + - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES, $NEXT) {...}) + - metavariable-regex: + metavariable: $METHOD + regex: ^(get|post|put|head|delete|options)$ + - pattern-either: + - pattern: $REQ.query + - pattern: $REQ.body + - pattern: $REQ.params + - pattern: $REQ.cookies + - pattern: $REQ.headers + - patterns: + - pattern-either: + - pattern-inside: | + ({ $REQ }: Request,$RES: Response, $NEXT: NextFunction) => + {...} + - pattern-inside: | + ({ $REQ }: Request,$RES: Response) => {...} + - focus-metavariable: $REQ + - pattern-either: + - pattern: params + - pattern: query + - pattern: cookies + - pattern: headers + - pattern: body + pattern-sinks: + - pattern-either: + - patterns: + - pattern-either: + - pattern-inside: | + $PUG = require('pug') + ... + - pattern-inside: | + import * as $PUG from 'pug' + ... + - pattern-inside: | + $PUG = require('jade') + ... + - pattern-inside: | + import * as $PUG from 'jade' + ... + - pattern-either: + - pattern: $PUG.compile(...) + - pattern: $PUG.compileClient(...) + - pattern: $PUG.compileClientWithDependenciesTracked(...) + - pattern: $PUG.render(...) + - patterns: + - pattern-either: + - pattern-inside: | + $PUG = require('dot') + ... + - pattern-inside: | + import * as $PUG from 'dot' + ... + - pattern-either: + - pattern: $PUG.template(...) + - pattern: $PUG.compile(...) + - patterns: + - pattern-either: + - pattern-inside: | + $PUG = require('ejs') + ... + - pattern-inside: | + import * as $PUG from 'ejs' + ... + - pattern-either: + - pattern: $PUG.render(...) + - patterns: + - pattern-either: + - pattern-inside: | + $PUG = require('nunjucks') + ... + - pattern-inside: | + import * as $PUG from 'nunjucks' + ... + - pattern-either: + - pattern: $PUG.renderString(...) + - patterns: + - pattern-either: + - pattern-inside: | + $PUG = require('lodash') + ... + - pattern-inside: | + import * as $PUG from 'lodash' + ... + - pattern-either: + - pattern: $PUG.template(...) + - patterns: + - pattern-either: + - pattern-inside: | + $PUG = require('mustache') + ... + - pattern-inside: | + import * as $PUG from 'mustache' + ... + - pattern-inside: | + $PUG = require('eta') + ... + - pattern-inside: | + import * as $PUG from 'eta' + ... + - pattern-inside: | + $PUG = require('squirrelly') + ... + - pattern-inside: | + import * as $PUG from 'squirrelly' + ... + - pattern-either: + - pattern: $PUG.render(...) + - patterns: + - pattern-either: + - pattern-inside: | + $PUG = require('hogan.js') + ... + - pattern-inside: | + import * as $PUG from 'hogan.js' + ... + - pattern-inside: | + $PUG = require('handlebars') + ... + - pattern-inside: | + import * as $PUG from 'handlebars' + ... + - pattern-either: + - pattern: $PUG.compile(...) +- id: javascript.express.security.express-jwt-hardcoded-secret.express-jwt-hardcoded-secret + message: >- + A hard-coded credential was detected. It is not recommended to store credentials in source-code, + as this risks secrets + being leaked and used by either an internal or external malicious adversary. It is recommended to + use environment variables to securely provide credentials or retrieve credentials from a secure + vault or HSM (Hardware Security Module). + options: + interfile: true + metadata: + interfile: true + cwe: + - 'CWE-798: Use of Hard-coded Credentials' + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + owasp: + - A07:2021 - Identification and Authentication Failures + category: security + technology: + - express + - secrets + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: HIGH + impact: MEDIUM + confidence: HIGH + languages: + - javascript + - typescript + severity: WARNING + patterns: + - pattern-either: + - pattern-inside: | + $JWT = require('express-jwt'); + ... + - pattern-inside: | + import $JWT from 'express-jwt'; + ... + - pattern-inside: | + import * as $JWT from 'express-jwt'; + ... + - pattern-inside: | + import { ..., $JWT, ... } from 'express-jwt'; + ... + - pattern-either: + - pattern: | + $JWT({...,secret: "$Y",...},...) + - pattern: | + $OPTS = "$Y"; + ... + $JWT({...,secret: $OPTS},...); + - focus-metavariable: $Y +- id: javascript.express.security.express-phantom-injection.express-phantom-injection + message: >- + If unverified user data can reach the `phantom` methods it can result in Server-Side Request Forgery + vulnerabilities + metadata: + owasp: + - A10:2021 - Server-Side Request Forgery (SSRF) + cwe: + - 'CWE-918: Server-Side Request Forgery (SSRF)' + category: security + technology: + - express + references: + - https://phantomjs.org/page-automation.html + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + languages: + - javascript + - typescript + severity: ERROR + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - pattern-inside: function ... ($REQ, $RES) {...} + - pattern-inside: function ... ($REQ, $RES, $NEXT) {...} + - patterns: + - pattern-either: + - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES) {...}) + - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES, $NEXT) {...}) + - metavariable-regex: + metavariable: $METHOD + regex: ^(get|post|put|head|delete|options)$ + - pattern-either: + - pattern: $REQ.query + - pattern: $REQ.body + - pattern: $REQ.params + - pattern: $REQ.cookies + - pattern: $REQ.headers + - patterns: + - pattern-either: + - pattern-inside: | + ({ $REQ }: Request,$RES: Response, $NEXT: NextFunction) => + {...} + - pattern-inside: | + ({ $REQ }: Request,$RES: Response) => {...} + - focus-metavariable: $REQ + - pattern-either: + - pattern: params + - pattern: query + - pattern: cookies + - pattern: headers + - pattern: body + pattern-sinks: + - patterns: + - pattern-either: + - pattern-inside: | + require('phantom'); + ... + - pattern-inside: | + import 'phantom'; + ... + - pattern-either: + - pattern: $PAGE.open($SINK,...) + - pattern: $PAGE.setContent($SINK,...) + - pattern: $PAGE.openUrl($SINK,...) + - pattern: $PAGE.evaluateJavaScript($SINK,...) + - pattern: $PAGE.property("content",$SINK,...) + - focus-metavariable: $SINK +- id: javascript.express.security.express-puppeteer-injection.express-puppeteer-injection + message: >- + If unverified user data can reach the `puppeteer` methods it can result in Server-Side Request Forgery + vulnerabilities + metadata: + owasp: + - A10:2021 - Server-Side Request Forgery (SSRF) + cwe: + - 'CWE-918: Server-Side Request Forgery (SSRF)' + category: security + technology: + - express + references: + - https://pptr.dev/api/puppeteer.page + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + languages: + - javascript + - typescript + severity: ERROR + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - pattern-inside: function ... ($REQ, $RES) {...} + - pattern-inside: function ... ($REQ, $RES, $NEXT) {...} + - patterns: + - pattern-either: + - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES) {...}) + - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES, $NEXT) {...}) + - metavariable-regex: + metavariable: $METHOD + regex: ^(get|post|put|head|delete|options)$ + - pattern-either: + - pattern: $REQ.query + - pattern: $REQ.body + - pattern: $REQ.params + - pattern: $REQ.cookies + - pattern: $REQ.headers + - patterns: + - pattern-either: + - pattern-inside: | + ({ $REQ }: Request,$RES: Response, $NEXT: NextFunction) => + {...} + - pattern-inside: | + ({ $REQ }: Request,$RES: Response) => {...} + - focus-metavariable: $REQ + - pattern-either: + - pattern: params + - pattern: query + - pattern: cookies + - pattern: headers + - pattern: body + pattern-sinks: + - patterns: + - pattern-either: + - pattern-inside: | + require('puppeteer'); + ... + - pattern-inside: | + import 'puppeteer'; + ... + - pattern-either: + - pattern: $PAGE.goto($SINK,...) + - pattern: $PAGE.setContent($SINK,...) + - pattern: $PAGE.evaluate($SINK,...) + - pattern: $PAGE.evaluate($CODE,$SINK,...) + - pattern: $PAGE.evaluateHandle($SINK,...) + - pattern: $PAGE.evaluateHandle($CODE,$SINK,...) + - pattern: $PAGE.evaluateOnNewDocument($SINK,...) + - pattern: $PAGE.evaluateOnNewDocument($CODE,$SINK,...) + - focus-metavariable: $SINK +- id: javascript.express.security.express-sandbox-injection.express-sandbox-code-injection + message: >- + Make sure that unverified user data can not reach `sandbox`. + metadata: + owasp: + - A03:2021 - Injection + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Injection_Prevention_Cheat_Sheet.html + cwe: + - "CWE-94: Improper Control of Generation of Code ('Code Injection')" + category: security + technology: + - express + cwe2022-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + languages: + - javascript + - typescript + severity: ERROR + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - pattern-inside: function ... ($REQ, $RES) {...} + - pattern-inside: function ... ($REQ, $RES, $NEXT) {...} + - patterns: + - pattern-either: + - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES) {...}) + - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES, $NEXT) {...}) + - metavariable-regex: + metavariable: $METHOD + regex: ^(get|post|put|head|delete|options)$ + - pattern-either: + - pattern: $REQ.query + - pattern: $REQ.body + - pattern: $REQ.params + - pattern: $REQ.cookies + - pattern: $REQ.headers + - patterns: + - pattern-either: + - pattern-inside: | + ({ $REQ }: Request,$RES: Response, $NEXT: NextFunction) => + {...} + - pattern-inside: | + ({ $REQ }: Request,$RES: Response) => {...} + - focus-metavariable: $REQ + - pattern-either: + - pattern: params + - pattern: query + - pattern: cookies + - pattern: headers + - pattern: body + pattern-sinks: + - patterns: + - pattern-inside: | + $SANDBOX = require('sandbox'); + ... + - pattern-either: + - patterns: + - pattern-inside: | + $S = new $SANDBOX(...); + ... + - pattern: | + $S.run(...) + - pattern: | + new $SANDBOX($OPTS).run(...) + - pattern: |- + new $SANDBOX().run(...) +- id: javascript.express.security.express-vm-injection.express-vm-injection + message: >- + Make sure that unverified user data can not reach `$VM`. + metadata: + owasp: + - A03:2021 - Injection + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Injection_Prevention_Cheat_Sheet.html + cwe: + - "CWE-94: Improper Control of Generation of Code ('Code Injection')" + category: security + technology: + - express + cwe2022-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + languages: + - javascript + - typescript + severity: ERROR + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - pattern-inside: function ... ($REQ, $RES) {...} + - pattern-inside: function ... ($REQ, $RES, $NEXT) {...} + - patterns: + - pattern-either: + - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES) {...}) + - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES, $NEXT) {...}) + - metavariable-regex: + metavariable: $METHOD + regex: ^(get|post|put|head|delete|options)$ + - pattern-either: + - pattern: $REQ.query + - pattern: $REQ.body + - pattern: $REQ.params + - pattern: $REQ.cookies + - pattern: $REQ.headers + - patterns: + - pattern-either: + - pattern-inside: | + ({ $REQ }: Request,$RES: Response, $NEXT: NextFunction) => + {...} + - pattern-inside: | + ({ $REQ }: Request,$RES: Response) => {...} + - focus-metavariable: $REQ + - pattern-either: + - pattern: params + - pattern: query + - pattern: cookies + - pattern: headers + - pattern: body + pattern-sinks: + - patterns: + - pattern-inside: | + $VM = require('vm'); + ... + - pattern-either: + - pattern: | + $VM.runInContext(...) + - pattern: | + $VM.runInNewContext(...) + - pattern: | + $VM.compileFunction(...) + - pattern: | + $VM.runInThisContext(...) + - pattern: |- + new $VM.Script(...) +- id: javascript.express.security.express-vm2-injection.express-vm2-injection + message: >- + Make sure that unverified user data can not reach `vm2`. + metadata: + owasp: + - A03:2021 - Injection + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Injection_Prevention_Cheat_Sheet.html + cwe: + - "CWE-94: Improper Control of Generation of Code ('Code Injection')" + category: security + technology: + - express + cwe2022-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + languages: + - javascript + - typescript + severity: WARNING + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - pattern-inside: function ... ($REQ, $RES) {...} + - pattern-inside: function ... ($REQ, $RES, $NEXT) {...} + - patterns: + - pattern-either: + - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES) {...}) + - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES, $NEXT) {...}) + - metavariable-regex: + metavariable: $METHOD + regex: ^(get|post|put|head|delete|options)$ + - pattern-either: + - pattern: $REQ.query + - pattern: $REQ.body + - pattern: $REQ.params + - pattern: $REQ.cookies + - pattern: $REQ.headers + - patterns: + - pattern-either: + - pattern-inside: | + ({ $REQ }: Request,$RES: Response, $NEXT: NextFunction) => + {...} + - pattern-inside: | + ({ $REQ }: Request,$RES: Response) => {...} + - focus-metavariable: $REQ + - pattern-either: + - pattern: params + - pattern: query + - pattern: cookies + - pattern: headers + - pattern: body + pattern-sinks: + - patterns: + - pattern-inside: | + require('vm2') + ... + - pattern-either: + - patterns: + - pattern-either: + - pattern-inside: | + $VM = new VM(...) + ... + - pattern-inside: | + $VM = new NodeVM(...) + ... + - pattern: | + $VM.run(...) + - pattern: | + new VM(...).run(...) + - pattern: | + new NodeVM(...).run(...) + - pattern: | + new VMScript(...) + - pattern: | + new VM(...) + - pattern: |- + new NodeVM(...) +- id: javascript.express.security.express-wkhtml-injection.express-wkhtmltoimage-injection + message: >- + If unverified user data can reach the `phantom` methods it can result in Server-Side Request Forgery vulnerabilities + metadata: + owasp: + - A10:2021 - Server-Side Request Forgery (SSRF) + cwe: + - 'CWE-918: Server-Side Request Forgery (SSRF)' + category: security + technology: + - express + references: + - https://www.npmjs.com/package/wkhtmltopdf + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: LOW + severity: ERROR + languages: [javascript, typescript] + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - pattern-inside: function ... ($REQ, $RES) {...} + - pattern-inside: function ... ($REQ, $RES, $NEXT) {...} + - patterns: + - pattern-either: + - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES) {...}) + - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES, $NEXT) {...}) + - metavariable-regex: + metavariable: $METHOD + regex: ^(get|post|put|head|delete|options)$ + - pattern-either: + - pattern: $REQ.query + - pattern: $REQ.body + - pattern: $REQ.params + - pattern: $REQ.cookies + - pattern: $REQ.headers + - patterns: + - pattern-either: + - pattern-inside: | + ({ $REQ }: Request,$RES: Response, $NEXT: NextFunction) => + {...} + - pattern-inside: | + ({ $REQ }: Request,$RES: Response) => {...} + - focus-metavariable: $REQ + - pattern-either: + - pattern: params + - pattern: query + - pattern: cookies + - pattern: headers + - pattern: body + pattern-sinks: + - patterns: + - pattern: $WK.generate($SINK,...) + - focus-metavariable: $SINK +- id: javascript.express.security.express-wkhtml-injection.express-wkhtmltopdf-injection + message: >- + If unverified user data can reach the `wkhtmltopdf` methods it can result in Server-Side Request Forgery + vulnerabilities + metadata: + owasp: + - A10:2021 - Server-Side Request Forgery (SSRF) + cwe: + - 'CWE-918: Server-Side Request Forgery (SSRF)' + category: security + technology: + - express + references: + - https://www.npmjs.com/package/wkhtmltopdf + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: LOW + languages: + - javascript + - typescript + severity: ERROR + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - pattern-inside: function ... ($REQ, $RES) {...} + - pattern-inside: function ... ($REQ, $RES, $NEXT) {...} + - patterns: + - pattern-either: + - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES) {...}) + - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES, $NEXT) {...}) + - metavariable-regex: + metavariable: $METHOD + regex: ^(get|post|put|head|delete|options)$ + - pattern-either: + - pattern: $REQ.query + - pattern: $REQ.body + - pattern: $REQ.params + - pattern: $REQ.cookies + - pattern: $REQ.headers + - patterns: + - pattern-either: + - pattern-inside: | + ({ $REQ }: Request,$RES: Response, $NEXT: NextFunction) => + {...} + - pattern-inside: | + ({ $REQ }: Request,$RES: Response) => {...} + - focus-metavariable: $REQ + - pattern-either: + - pattern: params + - pattern: query + - pattern: cookies + - pattern: headers + - pattern: body + pattern-sinks: + - patterns: + - pattern-inside: | + $WK = require('wkhtmltopdf'); + ... + - pattern: $WK($SINK,...) + - focus-metavariable: $SINK +- id: javascript.express.security.express-xml2json-xxe.express-xml2json-xxe + message: >- + Make sure that unverified user data can not reach the XML Parser, + as it can result in XML External or Internal Entity (XXE) Processing vulnerabilities + metadata: + owasp: + - A04:2017 - XML External Entities (XXE) + - A05:2021 - Security Misconfiguration + cwe: + - 'CWE-611: Improper Restriction of XML External Entity Reference' + asvs: + section: V5 Validation, Sanitization and Encoding + control_id: 5.5.2 Insecue XML Deserialization + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x13-V5-Validation-Sanitization-Encoding.md#v55-deserialization-prevention + version: '4' + category: security + technology: + - express + references: + - https://www.npmjs.com/package/xml2json + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + languages: + - javascript + - typescript + severity: ERROR + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - pattern-inside: function ... ($REQ, $RES) {...} + - pattern-inside: function ... ($REQ, $RES, $NEXT) {...} + - patterns: + - pattern-either: + - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES) {...}) + - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES, $NEXT) {...}) + - metavariable-regex: + metavariable: $METHOD + regex: ^(get|post|put|head|delete|options)$ + - pattern-either: + - pattern: $REQ.query + - pattern: $REQ.body + - pattern: $REQ.params + - pattern: $REQ.cookies + - pattern: $REQ.headers + - pattern: $REQ.files.$ANYTHING.data.toString('utf8') + - pattern: $REQ.files.$ANYTHING['data'].toString('utf8') + - patterns: + - pattern-either: + - pattern-inside: | + ({ $REQ }: Request,$RES: Response, $NEXT: NextFunction) => + {...} + - pattern-inside: | + ({ $REQ }: Request,$RES: Response) => {...} + - focus-metavariable: $REQ + - pattern-either: + - pattern: params + - pattern: query + - pattern: cookies + - pattern: headers + - pattern: body + - pattern: files.$ANYTHING.data.toString('utf8') + - pattern: files.$ANYTHING['data'].toString('utf8') + pattern-sinks: + - patterns: + - pattern-either: + - pattern-inside: | + require('xml2json'); + ... + - pattern-inside: | + import 'xml2json'; + ... + - pattern: $EXPAT.toJson($SINK,...) + - focus-metavariable: $SINK +- id: javascript.express.security.injection.raw-html-format.raw-html-format + message: >- + User data flows into the host portion of this manually-constructed HTML. + This can introduce a Cross-Site-Scripting (XSS) vulnerability if this comes from user-provided input. + Consider using a sanitization library such as DOMPurify to sanitize the HTML within. + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html + category: security + technology: + - express + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: HIGH + impact: MEDIUM + confidence: MEDIUM + languages: + - javascript + - typescript + severity: WARNING + mode: taint + pattern-sources: + - label: EXPRESS + patterns: + - pattern-either: + - pattern-inside: function ... ($REQ, $RES) {...} + - pattern-inside: function ... ($REQ, $RES, $NEXT) {...} + - patterns: + - pattern-either: + - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES) {...}) + - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES, $NEXT) {...}) + - metavariable-regex: + metavariable: $METHOD + regex: ^(get|post|put|head|delete|options)$ + - pattern-either: + - pattern: $REQ.query + - pattern: $REQ.body + - pattern: $REQ.params + - pattern: $REQ.cookies + - pattern: $REQ.headers + - label: EXPRESSTS + patterns: + - pattern-either: + - pattern-inside: | + ({ $REQ }: Request,$RES: Response, $NEXT: NextFunction) => + {...} + - pattern-inside: | + ({ $REQ }: Request,$RES: Response) => {...} + - focus-metavariable: $REQ + - pattern-either: + - pattern: params + - pattern: query + - pattern: cookies + - pattern: headers + - pattern: body + - label: CLEAN + by-side-effect: true + patterns: + - pattern-either: + - pattern: $A($SOURCE) + - pattern: $SANITIZE. ... .$A($SOURCE) + - pattern: $A. ... .$SANITIZE($SOURCE) + - focus-metavariable: $SOURCE + - metavariable-regex: + metavariable: $A + regex: (?i)(.*valid|.*sanitiz) + pattern-sinks: + - requires: (EXPRESS and not CLEAN) or (EXPRESSTS and not CLEAN) + patterns: + - pattern-either: + - patterns: + - pattern-either: + - pattern: '"$HTMLSTR" + $EXPR' + - pattern: '"$HTMLSTR".concat(...)' + - pattern: util.format($HTMLSTR, ...) + - metavariable-pattern: + metavariable: $HTMLSTR + language: generic + pattern: <$TAG ... + - patterns: + - pattern: | + `...` + - pattern-regex: | + .*<\w+.* +- id: javascript.express.security.injection.tainted-sql-string.tainted-sql-string + message: >- + Detected user input used to manually construct a SQL string. This is + usually bad practice because manual construction could accidentally result + in a SQL injection. An attacker could use a SQL injection to steal or + modify contents of the database. Instead, use a parameterized query which + is available by default in most database engines. Alternatively, consider + using an object-relational mapper (ORM) such as Sequelize which will + protect your queries. + metadata: + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + cwe: + - "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')" + references: + - https://owasp.org/www-community/attacks/SQL_Injection + category: security + technology: + - express + license: Commons Clause License Condition v1.0[LGPL-2.1-only] + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: HIGH + impact: MEDIUM + confidence: MEDIUM + languages: + - javascript + - typescript + severity: ERROR + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - pattern-inside: function ... (...,$REQ, ...) {...} + - pattern-either: + - pattern: $REQ.query + - pattern: $REQ.body + - pattern: $REQ.params + - pattern: $REQ.cookies + - pattern: $REQ.headers + - patterns: + - pattern-either: + - pattern-inside: > + (...,{ $REQ }: Request,...) => + {...} + - pattern-inside: | + (...,{ $REQ }: $EXPRESS.Request,...) => {...} + - focus-metavariable: $REQ + - pattern-either: + - pattern: params + - pattern: query + - pattern: cookies + - pattern: headers + - pattern: body + pattern-sinks: + - patterns: + - pattern-either: + - patterns: + - pattern-either: + - pattern-inside: | + "$SQLSTR" + $EXPR + - pattern-inside: | + "$SQLSTR".concat($EXPR) + - pattern: util.format($SQLSTR, $EXPR) + - pattern: | + `$SQLSTR${$EXPR}...` + - metavariable-regex: + metavariable: $SQLSTR + regex: .*\b(?i)(select|delete|insert|create|update\s+.+\sset|alter|drop)\b.* + - focus-metavariable: $EXPR +- id: javascript.express.security.require-request.require-request + message: >- + If an attacker controls the x in require(x) then they can cause code to load that was not intended + to run on the server. + options: + interfile: true + metadata: + interfile: true + owasp: + - A01:2021 - Broken Access Control + cwe: + - 'CWE-706: Use of Incorrectly-Resolved Name or Reference' + source-rule-url: https://nodesecroadmap.fyi/chapter-1/threat-UIR.html + category: security + technology: + - express + references: + - https://github.com/google/node-sec-roadmap/blob/master/chapter-2/dynamism.md#dynamism-when-you-need-it + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + languages: + - javascript + - typescript + severity: ERROR + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - pattern-inside: function ... ($REQ, $RES) {...} + - pattern-inside: function ... ($REQ, $RES, $NEXT) {...} + - patterns: + - pattern-either: + - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES) {...}) + - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES, $NEXT) {...}) + - metavariable-regex: + metavariable: $METHOD + regex: ^(get|post|put|head|delete|options)$ + - pattern-either: + - pattern: $REQ.query + - pattern: $REQ.body + - pattern: $REQ.params + - pattern: $REQ.cookies + - pattern: $REQ.headers + - patterns: + - pattern-either: + - pattern-inside: | + ({ $REQ }: Request,$RES: Response, $NEXT: NextFunction) => + {...} + - pattern-inside: | + ({ $REQ }: Request,$RES: Response) => {...} + - focus-metavariable: $REQ + - pattern-either: + - pattern: params + - pattern: query + - pattern: cookies + - pattern: headers + - pattern: body + pattern-sinks: + - patterns: + - pattern: require($SINK) + - focus-metavariable: $SINK +- id: javascript.express.security.x-frame-options-misconfiguration.x-frame-options-misconfiguration + message: >- + By letting user input control `X-Frame-Options` header, + there is a risk that software does not properly verify whether or not a browser should be allowed + to render a page in + an `iframe`. + metadata: + references: + - https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options + owasp: + - A04:2021 - Insecure Design + cwe: + - 'CWE-451: User Interface (UI) Misrepresentation of Critical Information' + category: security + technology: + - express + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + languages: + - javascript + - typescript + severity: WARNING + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - pattern-inside: function ... ($REQ, $RES) {...} + - pattern-inside: function ... ($REQ, $RES, $NEXT) {...} + - patterns: + - pattern-either: + - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES) {...}) + - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES, $NEXT) {...}) + - metavariable-regex: + metavariable: $METHOD + regex: ^(get|post|put|head|delete|options)$ + - pattern-either: + - pattern: $REQ.query + - pattern: $REQ.body + - pattern: $REQ.params + - pattern: $REQ.cookies + - pattern: $REQ.headers + - patterns: + - pattern-either: + - pattern-inside: | + ({ $REQ }: Request,$RES: Response, $NEXT: NextFunction) => + {...} + - pattern-inside: | + ({ $REQ }: Request,$RES: Response) => {...} + - focus-metavariable: $REQ + - pattern-either: + - pattern: params + - pattern: query + - pattern: cookies + - pattern: headers + - pattern: body + pattern-sinks: + - patterns: + - pattern-either: + - pattern: $RES.set($HEADER, ...) + - pattern: $RES.header($HEADER, ...) + - pattern: $RES.setHeader($HEADER, ...) + - pattern: | + $RES.set({$HEADER: ...}, ...) + - pattern: | + $RES.writeHead($STATUS, {$HEADER: ...}, ...) + - metavariable-regex: + metavariable: $HEADER + regex: .*(X-Frame-Options|x-frame-options).* +- id: javascript.fbjs.security.audit.insecure-createnodesfrommarkup.insecure-createnodesfrommarkup + message: >- + User controlled data in a `createNodesFromMarkup` is an anti-pattern that can lead to XSS vulnerabilities + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + category: security + technology: + - fbjs + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + references: + - https://owasp.org/Top10/A03_2021-Injection + languages: + - javascript + - typescript + severity: WARNING + patterns: + - pattern-either: + - pattern: createNodesFromMarkup(...) + - pattern: $X.createNodesFromMarkup(...) + - pattern-not: createNodesFromMarkup("...",...) + - pattern-not: $X.createNodesFromMarkup("...",...) +- id: javascript.grpc.security.grpc-nodejs-insecure-connection.grpc-nodejs-insecure-connection + message: >- + Found an insecure gRPC connection. This creates a connection without encryption to a gRPC client/server. + A malicious attacker could tamper with the gRPC message, which could compromise the machine. + metadata: + owasp: + - A08:2017 - Insecure Deserialization + - A08:2021 - Software and Data Integrity Failures + cwe: + - 'CWE-502: Deserialization of Untrusted Data' + category: security + technology: + - grpc + references: + - https://blog.gopheracademy.com/advent-2017/go-grpc-beyond-basics/#:~:text=disables%20transport%20security + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + languages: + - javascript + - typescript + severity: ERROR + pattern-either: + - pattern: | + require('grpc'); + ... + $GRPC($ADDR,...,$CREDENTIALS.createInsecure(),...); + - pattern: | + require('grpc'); + ... + new $GRPC($ADDR,...,$CREDENTIALS.createInsecure(),...); + - pattern: |- + require('grpc'); + ... + $CREDS = <... $CREDENTIALS.createInsecure() ...>; + ... + $GRPC($ADDR,...,$CREDS,...); + - pattern: |- + require('grpc'); + ... + $CREDS = <... $CREDENTIALS.createInsecure() ...>; + ... + new $GRPC($ADDR,...,$CREDS,...); +- id: javascript.intercom.security.audit.intercom-settings-user-identifier-without-user-hash.intercom-settings-user-identifier-without-user-hash + patterns: + - pattern-either: + - pattern: | + window.intercomSettings = {..., email: $EMAIL, ...}; + - pattern: | + window.intercomSettings = {..., user_id: $USER_ID, ...}; + - pattern: | + Intercom('boot', {..., email: $EMAIL, ...}); + - pattern: | + Intercom('boot', {..., user_id: $USER_ID, ...}); + - pattern: | + $VAR = {..., email: $EMAIL, ...}; + ... + Intercom('boot', $VAR); + - pattern: | + $VAR = {..., user_id: $EMAIL, ...}; + ... + Intercom('boot', $VAR); + - pattern-not: | + window.intercomSettings = {..., user_hash: $USER_HASH, ...}; + - pattern-not: | + Intercom('boot', {..., user_hash: $USER_HASH, ...}); + - pattern-not: | + $VAR = {..., user_hash: $USER_HASH, ...}; + ... + Intercom('boot', $VAR); + message: Found an initialization of the Intercom Messenger that identifies a + User, but does not specify a `user_hash`.This configuration allows users + to impersonate one another. See the Intercom Identity Verification docs + for more context + https://www.intercom.com/help/en/articles/183-set-up-identity-verification-for-web-and-mobile + languages: + - js + severity: WARNING + metadata: + category: security + subcategory: + - guardrail + cwe: + - "CWE-287: Improper Authentication" + confidence: MEDIUM + likelihood: MEDIUM + impact: HIGH + technology: + - intercom + references: + - https://www.intercom.com/help/en/articles/183-set-up-identity-verification-for-web-and-mobile +- id: javascript.jose.security.audit.jose-exposed-data.jose-exposed-data + message: >- + The object is passed strictly to jose.JWT.sign(...) + Make sure that sensitive information is not exposed through JWT token payload. + metadata: + owasp: + - A02:2017 - Broken Authentication + - A04:2021 - Insecure Design + cwe: + - 'CWE-522: Insufficiently Protected Credentials' + source-rule-url: https://semgrep.dev/blog/2020/hardcoded-secrets-unverified-tokens-and-other-common-jwt-mistakes/ + asvs: + section: 'V3: Session Management Verification Requirements' + control_id: 3.5.2 Static API keys or secret + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x12-V3-Session-management.md#v35-token-based-session-management + version: '4' + category: security + technology: + - jose + - jwt + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + references: + - https://owasp.org/Top10/A04_2021-Insecure_Design + languages: + - javascript + - typescript + severity: WARNING + patterns: + - pattern-inside: | + require('jose'); + ... + - pattern-either: + - patterns: + - pattern-inside: function (...,$INPUT,...) {...} + - pattern-either: + - pattern: $JOSE.JWT.sign($INPUT,...) + - pattern: $JWT.sign($INPUT,...) + - patterns: + - pattern-inside: function $F(...,$INPUT,...) {...} + - pattern-either: + - pattern: $JOSE.JWT.sign($INPUT,...) + - pattern: $JWT.sign($INPUT,...) +- id: javascript.jose.security.jwt-hardcode.hardcoded-jwt-secret + message: >- + A hard-coded credential was detected. It is not recommended to store credentials in source-code, + as this risks secrets + being leaked and used by either an internal or external malicious adversary. It is recommended to + use environment variables to securely provide credentials or retrieve credentials from a secure + vault or HSM (Hardware Security Module). + metadata: + interfile: true + cwe: + - 'CWE-798: Use of Hard-coded Credentials' + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + owasp: + - A07:2021 - Identification and Authentication Failures + asvs: + section: 'V3: Session Management Verification Requirements' + control_id: 3.5.2 Static API keys or secret + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x12-V3-Session-management.md#v35-token-based-session-management + version: '4' + category: security + technology: + - jose + - jwt + - secrets + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: HIGH + impact: MEDIUM + confidence: HIGH + languages: + - javascript + - typescript + severity: WARNING + patterns: + - pattern-inside: | + $JOSE = require("jose"); + ... + - pattern-either: + - pattern-inside: | + var {JWT} = $JOSE; + ... + - pattern-inside: | + var {JWK, JWT} = $JOSE; + ... + - pattern-inside: | + const {JWT} = $JOSE; + ... + - pattern-inside: | + const {JWK, JWT} = $JOSE; + ... + - pattern-inside: | + let {JWT} = $JOSE; + ... + - pattern-inside: | + let {JWK, JWT} = $JOSE; + ... + - pattern-either: + - pattern: | + JWT.verify($P, "...", ...); + - pattern: | + JWT.sign($P, "...", ...); + - pattern: | + JWT.verify($P, JWK.asKey("..."), ...); + - pattern: | + $JWT.sign($P, JWK.asKey("..."), ...); + options: + symbolic_propagation: true + interfile: true +- id: javascript.jose.security.jwt-none-alg.jwt-none-alg + message: >- + Detected use of the 'none' algorithm in a JWT token. + The 'none' algorithm assumes the integrity of the token has already + been verified. This would allow a malicious actor to forge a JWT token + that will automatically be verified. Do not explicitly use the 'none' + algorithm. Instead, use an algorithm such as 'HS256'. + metadata: + cwe: + - 'CWE-327: Use of a Broken or Risky Cryptographic Algorithm' + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + source-rule-url: https://semgrep.dev/blog/2020/hardcoded-secrets-unverified-tokens-and-other-common-jwt-mistakes/ + asvs: + section: 'V3: Session Management Verification Requirements' + control_id: 3.5.3 Insecue Stateless Session Tokens + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x12-V3-Session-management.md#v35-token-based-session-management + version: '4' + category: security + technology: + - jose + - jwt + subcategory: + - vuln + likelihood: HIGH + impact: MEDIUM + confidence: HIGH + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + languages: + - javascript + - typescript + severity: ERROR + pattern-either: + - pattern: | + var $JOSE = require("jose"); + ... + var { JWK, JWT } = $JOSE; + ... + var $T = JWT.verify($P, JWK.None,...); + - pattern: | + var $JOSE = require("jose"); + ... + var { JWK, JWT } = $JOSE; + ... + $T = JWT.verify($P, JWK.None,...); + - pattern: | + var $JOSE = require("jose"); + ... + var { JWK, JWT } = $JOSE; + ... + JWT.verify($P, JWK.None,...); +- id: javascript.jquery.security.audit.jquery-insecure-method.jquery-insecure-method + message: >- + User controlled data in a jQuery's `.$METHOD(...)` is an anti-pattern that can lead to XSS vulnerabilities + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + references: + - https://owasp.org/www-community/attacks/xss/ + - https://bugs.jquery.com/ticket/9521 + category: security + technology: + - jquery + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + languages: + - javascript + - typescript + severity: WARNING + options: + symbolic_propagation: true + pattern-either: + - patterns: + - pattern-either: + - pattern: $.$METHOD($VAR,...) + - pattern: $(...).$METHOD($VAR,...) + - pattern: jQuery.$METHOD($VAR,...) + - pattern: jQuery(...).$METHOD($VAR,...) + - pattern-not: $.$METHOD("...",...) + - pattern-not: $(...).$METHOD("...",...) + - pattern-not: jQuery.$METHOD("...",...) + - pattern-not: jQuery(...).$METHOD("...",...) + - metavariable-regex: + metavariable: $METHOD + regex: ^(html|append|prepend|wrap|wrapInner|wrapAll|before|after|globalEval|getScript)$ + - patterns: + - pattern-either: + - pattern: $(...).$METHOD($VAR,...) + - pattern: jQuery(...).$METHOD($VAR,...) + - pattern-not: $("...",...).$METHOD(...) + - pattern-not: jQuery("...",...).$METHOD(...) + - metavariable-regex: + metavariable: $METHOD + regex: ^(appendTo|insertAfter|insertBefore|prependTo)$ +- id: javascript.jquery.security.audit.jquery-insecure-selector.jquery-insecure-selector + message: >- + User controlled data in a `$(...)` is an anti-pattern that can lead to XSS vulnerabilities + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + references: + - https://owasp.org/www-community/attacks/xss/ + - https://bugs.jquery.com/ticket/9521 + category: security + technology: + - jquery + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + languages: + - javascript + - typescript + severity: WARNING + patterns: + - pattern-either: + - pattern: | + $(<... window ...>) + - pattern: | + $(<... location ...>) + - patterns: + - pattern: | + $X = <... window ...>; + ... + $(<... $X ...>); + - focus-metavariable: $X + - patterns: + - pattern: | + $X = <... location ...>; + ... + $(<... $X ...>); + - focus-metavariable: $X + - patterns: + - pattern-either: + - pattern-inside: | + function $FUNC(..., $Y, ...) { + ... + } + - pattern-inside: | + function (..., $Y, ...) { + ... + } + - pattern-inside: | + function $FUNC(...,$Z,...) { + ... + $Y = <... $Z ...>; + ... + } + - pattern-inside: | + function (...,$Z,...) { + ... + $Y = <... $Z ...>; + ... + } + - pattern-either: + - pattern: | + $(<... $Y ...>) + - pattern: | + $("..." + (<... $Y ...>)) + - pattern: | + $((<... $Y ...>) + "...") + - pattern-not-inside: | + $JQUERY.each(function($INDEX, $Y) { + ... + }) + - focus-metavariable: $Y + - pattern-not: | + $(window) + - pattern-not: | + $(document) + - pattern-not: | + $(this) +- id: javascript.jquery.security.audit.prohibit-jquery-html.prohibit-jquery-html + message: >- + JQuery's `html` function is susceptible to Cross Site Scripting (XSS) attacks. + If you're just passing text, consider `text` instead. Otherwise, use a + function that escapes HTML such as edX's `HtmlUtils.setHtml()`. + metadata: + shortDesription: Use of JQuery's unsafe html() function. + help: | + ## Remediation + Avoid using JQuery's html() function. If the string is plain text, use the text() function instead. + Otherwise, use a function that escapes html such as edx's HtmlUtils.setHtml(). + tags: + - security + precision: high + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + references: + - https://edx.readthedocs.io/projects/edx-developer-guide/en/latest/preventing_xss/preventing_xss.html#javascript-concat-html + - https://stackoverflow.com/questions/8318581/html-vs-innerhtml-jquery-javascript-xss-attacks + - https://api.jquery.com/text/#text-text + category: security + technology: + - jquery + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + languages: + - javascript + - typescript + severity: WARNING + patterns: + - pattern: | + $X.html(...) + - pattern-not: | + $X.html("...",...) +- id: javascript.jsonwebtoken.security.audit.jwt-decode-without-verify.jwt-decode-without-verify + message: >- + Detected the decoding of a JWT token without a verify step. + JWT tokens must be verified before use, otherwise the token's + integrity is unknown. This means a malicious actor could forge + a JWT token with any claims. Call '.verify()' before using the token. + metadata: + cwe: + - 'CWE-345: Insufficient Verification of Data Authenticity' + owasp: + - A08:2021 - Software and Data Integrity Failures + source-rule-url: https://semgrep.dev/blog/2020/hardcoded-secrets-unverified-tokens-and-other-common-jwt-mistakes/ + asvs: + section: 'V3: Session Management Verification Requirements' + control_id: 3.5.3 Insecue Stateless Session Tokens + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x12-V3-Session-management.md#v35-token-based-session-management + version: '4' + category: security + technology: + - jwt + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + references: + - https://owasp.org/Top10/A08_2021-Software_and_Data_Integrity_Failures + languages: + - javascript + - typescript + severity: WARNING + patterns: + - pattern-inside: | + $JWT = require('jsonwebtoken'); + ... + - pattern-not-inside: | # nosemgrep: slow-pattern-top-ellipsis + ... + $JWT.verify($TOKEN, ...) + ... + - pattern-not-inside: | # nosemgrep: slow-pattern-top-ellipsis + ... + if (<... $JWT.verify($TOKEN, ...) ...>) { ... } + ... + - pattern: $JWT.decode($TOKEN, ...) +- id: javascript.jsonwebtoken.security.audit.jwt-exposed-data.jwt-exposed-data + message: >- + The object is passed strictly to jsonwebtoken.sign(...) + Make sure that sensitive information is not exposed through JWT token payload. + metadata: + owasp: + - A02:2017 - Broken Authentication + - A04:2021 - Insecure Design + cwe: + - 'CWE-522: Insufficiently Protected Credentials' + source-rule-url: https://semgrep.dev/blog/2020/hardcoded-secrets-unverified-tokens-and-other-common-jwt-mistakes/ + asvs: + section: 'V3: Session Management Verification Requirements' + control_id: 3.5.3 Insecue Stateless Session Tokens + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x12-V3-Session-management.md#v35-token-based-session-management + version: '4' + category: security + technology: + - jwt + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + references: + - https://owasp.org/Top10/A04_2021-Insecure_Design + languages: + - javascript + - typescript + severity: WARNING + patterns: + - pattern-inside: | + $JWT = require('jsonwebtoken'); + ... + - pattern-either: + - pattern-inside: function (...,$INPUT,...) {...} + - pattern-inside: function $F(...,$INPUT,...) {...} + - pattern: $JWT.sign($INPUT,...) +- id: javascript.jsonwebtoken.security.jwt-hardcode.hardcoded-jwt-secret + message: >- + A hard-coded credential was detected. It is not recommended to store credentials in source-code, + as this risks secrets + being leaked and used by either an internal or external malicious adversary. It is recommended to + use environment variables to securely provide credentials or retrieve credentials from a secure + vault or HSM (Hardware Security Module). + metadata: + cwe: + - 'CWE-798: Use of Hard-coded Credentials' + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + owasp: + - A07:2021 - Identification and Authentication Failures + asvs: + section: 'V3: Session Management Verification Requirements' + control_id: 3.5.2 Static API keys or secret + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x12-V3-Session-management.md#v35-token-based-session-management + version: '4' + category: security + technology: + - jwt + - javascript + - secrets + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: HIGH + impact: MEDIUM + confidence: HIGH + languages: + - javascript + - typescript + severity: WARNING + mode: taint + pattern-sources: + - patterns: + - pattern: | + $X = '...' + - pattern: | + $X = '$Y' + - patterns: + - pattern-either: + - pattern-inside: | + $JWT.sign($DATA,"...",...); + - pattern-inside: | + $JWT.verify($DATA,"...",...); + pattern-sinks: + - patterns: + - pattern-either: + - pattern-inside: | + $JWT = require("jsonwebtoken") + ... + - pattern-inside: | + import $JWT from "jsonwebtoken" + ... + - pattern-inside: | + import * as $JWT from "jsonwebtoken" + ... + - pattern-inside: | + import {...,$JWT,...} from "jsonwebtoken" + ... + - pattern-either: + - pattern-inside: | + $JWT.sign($DATA,$VALUE,...); + - pattern-inside: | + $JWT.verify($DATA,$VALUE,...); + - focus-metavariable: $VALUE +- id: javascript.jsonwebtoken.security.jwt-none-alg.jwt-none-alg + message: >- + Detected use of the 'none' algorithm in a JWT token. + The 'none' algorithm assumes the integrity of the token has already + been verified. This would allow a malicious actor to forge a JWT token + that will automatically be verified. Do not explicitly use the 'none' + algorithm. Instead, use an algorithm such as 'HS256'. + metadata: + cwe: + - 'CWE-327: Use of a Broken or Risky Cryptographic Algorithm' + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + source-rule-url: https://semgrep.dev/blog/2020/hardcoded-secrets-unverified-tokens-and-other-common-jwt-mistakes/ + asvs: + section: 'V3: Session Management Verification Requirements' + control_id: 3.5.3 Insecue Stateless Session Tokens + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x12-V3-Session-management.md#v35-token-based-session-management + version: '4' + category: security + technology: + - jwt + subcategory: + - vuln + likelihood: MEDIUM + impact: HIGH + confidence: MEDIUM + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + languages: + - javascript + - typescript + severity: ERROR + patterns: + - pattern-inside: | + $JWT = require("jsonwebtoken"); + ... + - pattern: $JWT.verify($P, $X, {algorithms:[...,'none',...]},...) +- id: javascript.jwt-simple.security.jwt-simple-noverify.jwt-simple-noverify + message: >- + Detected the decoding of a JWT token without a verify step. + JWT tokens must be verified before use, otherwise the token's + integrity is unknown. This means a malicious actor could forge + a JWT token with any claims. Set 'verify' to `true` before using the token. + severity: ERROR + metadata: + owasp: + - A05:2021 - Security Misconfiguration + - A07:2021 - Identification and Authentication Failures + cwe: + - 'CWE-287: Improper Authentication' + - 'CWE-345: Insufficient Verification of Data Authenticity' + - 'CWE-347: Improper Verification of Cryptographic Signature' + category: security + subcategory: + - vuln + technology: + - jwt-simple + - jwt + confidence: HIGH + likelihood: MEDIUM + impact: HIGH + references: + - https://www.npmjs.com/package/jwt-simple + - https://cwe.mitre.org/data/definitions/287 + - https://cwe.mitre.org/data/definitions/345 + - https://cwe.mitre.org/data/definitions/347 + languages: + - javascript + - typescript + patterns: + - pattern-inside: | + $JWT = require('jwt-simple'); + ... + - pattern: $JWT.decode($TOKEN, $SECRET, $NOVERIFY, ...) + - metavariable-pattern: + metavariable: $NOVERIFY + patterns: + - pattern-either: + - pattern: | + true + - pattern: | + "..." +- id: javascript.lang.best-practice.assigned-undefined.assigned-undefined + languages: + - javascript + - typescript + message: + '`undefined` is not a reserved keyword in Javascript, so this is "valid" Javascript but highly confusing and likely + to result in bugs.' + pattern-either: + - pattern: undefined = $X; + - pattern: var undefined = $X; + - pattern: let undefined = $X; + - pattern: const undefined = $X; + severity: WARNING + metadata: + category: best-practice + technology: + - javascript +- id: javascript.lang.best-practice.lazy-load-module.lazy-load-module + patterns: + - pattern: require(...) + - pattern-inside: | + function $NAME(...) { + ... + } + message: >- + Lazy loading can complicate code bundling if care is not taken, also `require`s + are run synchronously by Node.js. + If they are called from within a function, it may block other requests from being + handled at a more critical time. + The best practice is to `require` modules at the beginning of each file, before + and outside of any functions. + languages: [javascript, typescript] + severity: WARNING + metadata: + category: best-practice + technology: + - javascript + references: + - https://nodesecroadmap.fyi/chapter-2/dynamism.html + - https://github.com/goldbergyoni/nodebestpractices#-38-require-modules-first-not-inside-functions +- id: javascript.lang.best-practice.leftover_debugging.javascript-alert + message: found alert() call; should this be in production code? + languages: + - javascript + - typescript + severity: WARNING + pattern-either: + - pattern: alert() + - pattern: alert($X) + metadata: + category: best-practice + technology: + - javascript +- id: javascript.lang.best-practice.leftover_debugging.javascript-debugger + pattern: debugger; + message: found debugger call; should this be in production code? + languages: + - javascript + - typescript + severity: WARNING + metadata: + category: best-practice + technology: + - javascript +- id: javascript.lang.best-practice.leftover_debugging.javascript-confirm + pattern: confirm(...) + message: found confirm() call; should this be in production code? + languages: + - javascript + - typescript + severity: WARNING + metadata: + category: best-practice + technology: + - javascript +- id: javascript.lang.best-practice.leftover_debugging.javascript-prompt + message: found prompt() call; should this be in production code? + languages: + - javascript + - typescript + severity: WARNING + pattern-either: + - pattern: prompt() + - pattern: prompt($X) + - pattern: prompt($X, $Y) + metadata: + category: best-practice + technology: + - javascript +- id: javascript.lang.best-practice.zlib-async-loop.zlib-async-loop + patterns: + - pattern-either: + - pattern-inside: | + for (...) { + ... + } + - pattern-inside: | + while (...) { + ... + } + - pattern-inside: | + do { + ... + } while (...) + - pattern-inside: | + $SMTH.forEach(...) + - pattern-inside: | + $SMTH.map(...) + - pattern-inside: | + $SMTH.reduce(...) + - pattern-inside: | + $SMTH.reduceRight(...) + - pattern: zlib.$METHOD(...); + - metavariable-regex: + metavariable: $METHOD + regex: ^.+$(?- + Creating and using a large number of zlib objects simultaneously + can cause significant memory fragmentation. It is strongly recommended + that the results of compression operations be cached or made synchronous + to avoid duplication of effort. + metadata: + references: + - https://nodejs.org/api/zlib.html#zlib_threadpool_usage_and_performance_considerations + category: best-practice + technology: + - javascript + severity: WARNING + languages: [javascript, typescript] +- id: javascript.lang.correctness.missing-template-string-indicator.missing-template-string-indicator + patterns: + - pattern-inside: | + `...` + - pattern: $STR + - metavariable-regex: + metavariable: $STR + regex: .*[^$]+{[^{}]*}.* + languages: [javascript, typescript] + message: >- + This looks like a JavaScript template string. Are you missing a '$' in front of + '{...}'? + severity: INFO + metadata: + category: correctness + technology: + - js +- id: javascript.lang.correctness.no-replaceall.no-replaceall + message: >- + The string method replaceAll is not supported in all versions of javascript, and + is not supported by older browser versions. Consider using replace() with a regex + as the first argument instead like mystring.replace(/bad/g, "good") instead of + mystring.replaceAll("bad", "good") (https://discourse.threejs.org/t/replaceall-is-not-a-function/14585) + severity: WARNING + languages: + - javascript + - typescript + pattern: $STRING.replaceAll("...",$NEW) + metadata: + category: correctness + technology: + - javascript + references: + - https://discourse.threejs.org/t/replaceall-is-not-a-function/14585 +- id: javascript.lang.correctness.no-stringify-keys.no-stringify-keys + mode: taint + pattern-sources: + - pattern: JSON.stringify(...) + - patterns: + - pattern-inside: | + $STRINGIFY = JSON.stringify + ... + $STRINGIFY(...) + - pattern: $STRINGIFY(...) + pattern-sinks: + - pattern: $OBJECT[...] + message: >- + JSON stringify does not produce a stable key ordering, and should not + be relied on for producing object keys. Consider using json-stable-stringify + instead. + languages: + - javascript + - typescript + severity: WARNING + metadata: + category: correctness + references: + - https://www.npmjs.com/package/json-stable-stringify + - https://stackoverflow.com/a/16168003 + technology: + - javascript + - typescript +- id: javascript.lang.correctness.useless-assign.useless-assignment + patterns: + - pattern: | + $X = $Y; + $X = $Z; + - pattern-not: | + $X = $Y; + $X = <... $X ...>; + message: "`$X` is assigned twice; the first assignment is useless" + languages: + - javascript + - typescript + severity: INFO + metadata: + category: correctness + technology: + - javascript +- id: javascript.lang.correctness.useless-eqeq.eqeq-is-bad + patterns: + - pattern-not-inside: assert(...) + - pattern-either: + - pattern: $X == $X + - pattern: $X != $X + - pattern-not: 1 == 1 + message: >- + Detected a useless comparison operation `$X == $X` or `$X != $X`. This + operation is always true. + If testing for floating point NaN, use `math.isnan`, or + `cmath.isnan` if the number is complex. + languages: + - javascript + - typescript + severity: INFO + metadata: + category: correctness + technology: + - javascript +- id: javascript.lang.security.audit.code-string-concat.code-string-concat + message: >- + Found data from an Express or Next web request flowing to `eval`. If this data is user-controllable + this can lead to execution of arbitrary system commands in the context of your application process. + Avoid `eval` whenever possible. + options: + interfile: true + metadata: + interfile: true + confidence: HIGH + owasp: + - A03:2021 - Injection + cwe: + - "CWE-95: Improper Neutralization of Directives in Dynamically Evaluated Code ('Eval Injection')" + references: + - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval + - https://nodejs.org/api/child_process.html#child_processexeccommand-options-callback + - https://www.stackhawk.com/blog/nodejs-command-injection-examples-and-prevention/ + - https://ckarande.gitbooks.io/owasp-nodegoat-tutorial/content/tutorial/a1_-_server_side_js_injection.html + category: security + technology: + - node.js + - Express + - Next.js + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + languages: + - javascript + - typescript + severity: ERROR + mode: taint + pattern-sources: + - pattern-either: + - patterns: + - pattern-either: + - pattern-inside: function ... ($REQ, $RES) {...} + - pattern-inside: function ... ($REQ, $RES, $NEXT) {...} + - patterns: + - pattern-either: + - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES) {...}) + - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES, $NEXT) {...}) + - metavariable-regex: + metavariable: $METHOD + regex: ^(get|post|put|head|delete|options)$ + - pattern-either: + - pattern: $REQ.query + - pattern: $REQ.body + - pattern: $REQ.params + - pattern: $REQ.cookies + - pattern: $REQ.headers + - patterns: + - pattern-either: + - pattern-inside: | + import { ...,$IMPORT,... } from 'next/router' + ... + - pattern-inside: | + import $IMPORT from 'next/router'; + ... + - pattern-either: + - patterns: + - pattern-inside: | + $ROUTER = $IMPORT() + ... + - pattern-either: + - pattern-inside: | + const { ...,$PROPS,... } = $ROUTER.query + ... + - pattern-inside: | + var { ...,$PROPS,... } = $ROUTER.query + ... + - pattern-inside: | + let { ...,$PROPS,... } = $ROUTER.query + ... + - focus-metavariable: $PROPS + - patterns: + - pattern-inside: | + $ROUTER = $IMPORT() + ... + - pattern: | + $ROUTER.query.$VALUE + - patterns: + - pattern: $IMPORT().query.$VALUE + pattern-sinks: + - patterns: + - pattern: | + eval(...) +- id: javascript.lang.security.audit.dangerous-spawn-shell.dangerous-spawn-shell + message: >- + Detected non-literal calls to $EXEC(). This could lead to a command + injection vulnerability. + metadata: + cwe: + - "CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')" + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + source-rule-url: https://github.com/nodesecurity/eslint-plugin-security/blob/master/rules/detect-child-process.js + category: security + technology: + - javascript + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Nodejs_Security_Cheat_Sheet.html#do-not-use-dangerous-functions + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: HIGH + impact: MEDIUM + confidence: LOW + languages: + - javascript + - typescript + severity: ERROR + mode: taint + pattern-sources: + - patterns: + - pattern-inside: | + function ... (...,$FUNC,...) { + ... + } + - focus-metavariable: $FUNC + pattern-sinks: + - patterns: + - pattern-either: + - pattern-inside: | + require('child_process') + ... + - pattern-inside: | + import 'child_process' + ... + - pattern-either: + - pattern: spawn(...) + - pattern: spawnSync(...) + - pattern: $CP.spawn(...) + - pattern: $CP.spawnSync(...) + - pattern-either: + - pattern: | + $EXEC("=~/(sh|bash|ksh|csh|tcsh|zsh)/",["-c", $ARG, ...],...) + - patterns: + - pattern: $EXEC($CMD,["-c", $ARG, ...],...) + - pattern-inside: | + $CMD = "=~/(sh|bash|ksh|csh|tcsh|zsh)/" + ... + - pattern: | + $EXEC("=~/(sh|bash|ksh|csh|tcsh|zsh)/",[$ARG, ...],...) + - patterns: + - pattern: $EXEC($CMD,[$ARG, ...],...) + - pattern-inside: | + $CMD = "=~/(sh|bash|ksh|csh|tcsh|zsh)/" + ... + - focus-metavariable: $ARG +- id: javascript.lang.security.audit.detect-non-literal-fs-filename.detect-non-literal-fs-filename + message: >- + Detected that function argument `$ARG` has entered the fs module. An attacker could potentially control the location of this + file, to include going backwards in the directory with '../'. To address this, ensure that user-controlled + variables in file paths are validated. + metadata: + cwe: + - "CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')" + references: + - https://owasp.org/www-community/attacks/Path_Traversal + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + source-rule-url: https://github.com/nodesecurity/eslint-plugin-security/blob/master/rules/detect-non-literal-fs-filename.js + category: security + technology: + - typescript + license: Commons Clause License Condition v1.0[LGPL-2.1-only] + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: HIGH + impact: MEDIUM + confidence: LOW + languages: + - typescript + - javascript + severity: WARNING + mode: taint + pattern-sources: + - patterns: + - pattern-inside: function ... (..., $ARG,...) {...} + - focus-metavariable: $ARG + pattern-sinks: + - patterns: + - pattern-either: + - pattern-inside: | + $FS = require('fs') + ... + - pattern-inside: | + $FS = require('fs/promises') + ... + - pattern-inside: | + import * as $FS from 'fs' + ... + - pattern-inside: | + import $FS from 'fs' + ... + - pattern-inside: | + import * as $FS from 'fs/promises' + ... + - pattern-inside: | + import $FS from 'fs/promises' + ... + - pattern-not: $FS. ... .$METHOD("...", ...) + - pattern-either: + - pattern: $FS. ... .access($FILE,...) + - pattern: $FS. ... .appendFile($FILE,...) + - pattern: $FS. ... .chmod($FILE,...) + - pattern: $FS. ... .chown($FILE,...) + - pattern: $FS. ... .close($FILE,...) + - pattern: $FS. ... .copyFile($FILE,...) + - pattern: $FS. ... .copyFile($SMTH, $FILE,...) + - pattern: $FS. ... .cp($FILE, ...) + - pattern: $FS. ... .cp($SMTH, $FILE, ...) + - pattern: $FS. ... .createReadStream($FILE,...) + - pattern: $FS. ... .createWriteStream($FILE,...) + - pattern: $FS. ... .exists($FILE, ...) + - pattern: $FS. ... .fchmod($FILE, ...) + - pattern: $FS. ... .fchown($FILE, ...) + - pattern: $FS. ... .fdatasync($FILE, ...) + - pattern: $FS. ... .fstat($FILE, ...) + - pattern: $FS. ... .fsync($FILE, ...) + - pattern: $FS. ... .ftruncate($FILE, ...) + - pattern: $FS. ... .futimes($FILE, ...) + - pattern: $FS. ... .lchmod($FILE, ...) + - pattern: $FS. ... .lchown($FILE, ...) + - pattern: $FS. ... .lutimes($FILE, ...) + - pattern: $FS. ... .link($FILE, ...) + - pattern: $FS. ... .link($SMTH, $FILE, ...) + - pattern: $FS. ... .lstat($FILE, ...) + - pattern: $FS. ... .mkdir($FILE, ...) + - pattern: $FS. ... .mkdtemp($FILE, ...) + - pattern: $FS. ... .open($FILE, ...) + - pattern: $FS. ... .opendir($FILE, ...) + - pattern: $FS. ... .read($FILE, ...) + - pattern: $FS. ... .read($FILE, ...) + - pattern: $FS. ... .readdir($FILE, ...) + - pattern: $FS. ... .readFile($FILE, ...) + - pattern: $FS. ... .readlink($FILE, ...) + - pattern: $FS. ... .readv($FILE, ...) + - pattern: $FS. ... .realpath($FILE, ...) + - pattern: $FS. ... .realpath.native($FILE, ...) + - pattern: $FS. ... .rename($FILE, ...) + - pattern: $FS. ... .rename($SMTH, $FILE, ...) + - pattern: $FS. ... .rmdir($FILE, ...) + - pattern: $FS. ... .rm($FILE, ...) + - pattern: $FS. ... .stat($FILE, ...) + - pattern: $FS. ... .symlink($SMTH, $FILE, ...) + - pattern: $FS. ... .symlink($FILE, ...) + - pattern: $FS. ... .truncate($FILE, ...) + - pattern: $FS. ... .unlink($FILE, ...) + - pattern: $FS. ... .unwatchFile($FILE, ...) + - pattern: $FS. ... .utimes($FILE, ...) + - pattern: $FS. ... .watch($FILE, ...) + - pattern: $FS. ... .watchFile($FILE, ...) + - pattern: $FS. ... .write($FILE, ...) + - pattern: $FS. ... .writeFile($FILE, ...) + - pattern: $FS. ... .writev($FILE, ...) + - pattern: $FS. ... .accessSync($FILE, ...) + - pattern: $FS. ... .appendFileSync($FILE, ...) + - pattern: $FS. ... .chmodSync($FILE, ...) + - pattern: $FS. ... .chownSync($FILE, ...) + - pattern: $FS. ... .closeSync($FILE, ...) + - pattern: $FS. ... .copyFileSync($FILE, ...) + - pattern: $FS. ... .copyFileSync($SMTH, $FILE, ...) + - pattern: $FS. ... .cpSync($FILE, ...) + - pattern: $FS. ... .cpSync($SMTH, $FILE, ...) + - pattern: $FS. ... .existsSync($FILE, ...) + - pattern: $FS. ... .fchmodSync($FILE, ...) + - pattern: $FS. ... .fchownSync($FILE, ...) + - pattern: $FS. ... .fdatasyncSync($FILE, ...) + - pattern: $FS. ... .fstatSync($FILE, ...) + - pattern: $FS. ... .fsyncSync($FILE, ...) + - pattern: $FS. ... .ftruncateSync($FILE, ...) + - pattern: $FS. ... .futimesSync($FILE, ...) + - pattern: $FS. ... .lchmodSync($FILE, ...) + - pattern: $FS. ... .lchownSync($FILE, ...) + - pattern: $FS. ... .lutimesSync($FILE, ...) + - pattern: $FS. ... .linkSync($FILE, ...) + - pattern: $FS. ... .linkSync($SMTH, $FILE, ...) + - pattern: $FS. ... .lstatSync($FILE, ...) + - pattern: $FS. ... .mkdirSync($FILE, ...) + - pattern: $FS. ... .mkdtempSync($FILE, ...) + - pattern: $FS. ... .opendirSync($FILE, ...) + - pattern: $FS. ... .openSync($FILE, ...) + - pattern: $FS. ... .readdirSync($FILE, ...) + - pattern: $FS. ... .readFileSync($FILE, ...) + - pattern: $FS. ... .readlinkSync($FILE, ...) + - pattern: $FS. ... .readSync($FILE, ...) + - pattern: $FS. ... .readSync($FILE, ...) + - pattern: $FS. ... .readvSync($FILE, ...) + - pattern: $FS. ... .realpathync($FILE, ...) + - pattern: $FS. ... .realpathSync.native($FILE, ...) + - pattern: $FS. ... .renameSync($FILE, ...) + - pattern: $FS. ... .renameSync($SMTH, $FILE, ...) + - pattern: $FS. ... .rmdirSync($FILE, ...) + - pattern: $FS. ... .rmSync($FILE, ...) + - pattern: $FS. ... .statSync($FILE, ...) + - pattern: $FS. ... .symlinkSync($FILE, ...) + - pattern: $FS. ... .symlinkSync($SMTH, $FILE, ...) + - pattern: $FS. ... .truncateSync($FILE, ...) + - pattern: $FS. ... .unlinkSync($FILE, ...) + - pattern: $FS. ... .utimesSync($FILE, ...) + - pattern: $FS. ... .writeFileSync($FILE, ...) + - pattern: $FS. ... .writeSync($FILE, ...) + - pattern: $FS. ... .writevSync($FILE, ...) + - focus-metavariable: $FILE + - patterns: + - pattern-either: + - pattern-inside: | + import 'fs' + ... + - pattern-inside: | + import 'fs/promises' + ... + - pattern-not: $METHOD("...", ...) + - pattern-either: + - pattern: access($FILE,...) + - pattern: appendFile($FILE,...) + - pattern: chmod($FILE,...) + - pattern: chown($FILE,...) + - pattern: close($FILE,...) + - pattern: copyFile($FILE,...) + - pattern: copyFile($SMTH, $FILE,...) + - pattern: cp($FILE, ...) + - pattern: cp($SMTH, $FILE, ...) + - pattern: createReadStream($FILE,...) + - pattern: createWriteStream($FILE,...) + - pattern: exists($FILE, ...) + - pattern: fchmod($FILE, ...) + - pattern: fchown($FILE, ...) + - pattern: fdatasync($FILE, ...) + - pattern: fstat($FILE, ...) + - pattern: fsync($FILE, ...) + - pattern: ftruncate($FILE, ...) + - pattern: futimes($FILE, ...) + - pattern: lchmod($FILE, ...) + - pattern: lchown($FILE, ...) + - pattern: lutimes($FILE, ...) + - pattern: link($FILE, ...) + - pattern: link($SMTH, $FILE, ...) + - pattern: lstat($FILE, ...) + - pattern: mkdir($FILE, ...) + - pattern: mkdtemp($FILE, ...) + - pattern: open($FILE, ...) + - pattern: opendir($FILE, ...) + - pattern: read($FILE, ...) + - pattern: read($FILE, ...) + - pattern: readdir($FILE, ...) + - pattern: readFile($FILE, ...) + - pattern: readlink($FILE, ...) + - pattern: readv($FILE, ...) + - pattern: realpath($FILE, ...) + - pattern: realpath.native($FILE, ...) + - pattern: rename($FILE, ...) + - pattern: rename($SMTH, $FILE, ...) + - pattern: rmdir($FILE, ...) + - pattern: rm($FILE, ...) + - pattern: stat($FILE, ...) + - pattern: symlink($SMTH, $FILE, ...) + - pattern: symlink($FILE, ...) + - pattern: truncate($FILE, ...) + - pattern: unlink($FILE, ...) + - pattern: unwatchFile($FILE, ...) + - pattern: utimes($FILE, ...) + - pattern: watch($FILE, ...) + - pattern: watchFile($FILE, ...) + - pattern: write($FILE, ...) + - pattern: writeFile($FILE, ...) + - pattern: writev($FILE, ...) + - pattern: accessSync($FILE, ...) + - pattern: appendFileSync($FILE, ...) + - pattern: chmodSync($FILE, ...) + - pattern: chownSync($FILE, ...) + - pattern: closeSync($FILE, ...) + - pattern: copyFileSync($FILE, ...) + - pattern: copyFileSync($SMTH, $FILE, ...) + - pattern: cpSync($FILE, ...) + - pattern: cpSync($SMTH, $FILE, ...) + - pattern: existsSync($FILE, ...) + - pattern: fchmodSync($FILE, ...) + - pattern: fchownSync($FILE, ...) + - pattern: fdatasyncSync($FILE, ...) + - pattern: fstatSync($FILE, ...) + - pattern: fsyncSync($FILE, ...) + - pattern: ftruncateSync($FILE, ...) + - pattern: futimesSync($FILE, ...) + - pattern: lchmodSync($FILE, ...) + - pattern: lchownSync($FILE, ...) + - pattern: lutimesSync($FILE, ...) + - pattern: linkSync($FILE, ...) + - pattern: linkSync($SMTH, $FILE, ...) + - pattern: lstatSync($FILE, ...) + - pattern: mkdirSync($FILE, ...) + - pattern: mkdtempSync($FILE, ...) + - pattern: opendirSync($FILE, ...) + - pattern: openSync($FILE, ...) + - pattern: readdirSync($FILE, ...) + - pattern: readFileSync($FILE, ...) + - pattern: readlinkSync($FILE, ...) + - pattern: readSync($FILE, ...) + - pattern: readSync($FILE, ...) + - pattern: readvSync($FILE, ...) + - pattern: realpathync($FILE, ...) + - pattern: realpathSync.native($FILE, ...) + - pattern: renameSync($FILE, ...) + - pattern: renameSync($SMTH, $FILE, ...) + - pattern: rmdirSync($FILE, ...) + - pattern: rmSync($FILE, ...) + - pattern: statSync($FILE, ...) + - pattern: symlinkSync($FILE, ...) + - pattern: symlinkSync($SMTH, $FILE, ...) + - pattern: truncateSync($FILE, ...) + - pattern: unlinkSync($FILE, ...) + - pattern: utimesSync($FILE, ...) + - pattern: writeFileSync($FILE, ...) + - pattern: writeSync($FILE, ...) + - pattern: writevSync($FILE, ...) + - focus-metavariable: $FILE +- id: javascript.lang.security.audit.detect-non-literal-regexp.detect-non-literal-regexp + message: >- + RegExp() called with a `$ARG` function argument, this might allow an attacker to cause a Regular Expression + Denial-of-Service (ReDoS) within your application as RegExP blocks the main thread. For this reason, it is + recommended to use hardcoded regexes instead. If your regex is run on user-controlled input, consider performing + input validation or use a regex checking/sanitization library such as https://www.npmjs.com/package/recheck to + verify that the regex does not appear vulnerable to ReDoS. + metadata: + owasp: + - A05:2021 - Security Misconfiguration + - A06:2017 - Security Misconfiguration + cwe: + - "CWE-1333: Inefficient Regular Expression Complexity" + references: + - https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS + source-rule-url: https://github.com/nodesecurity/eslint-plugin-security/blob/master/rules/detect-non-literal-regexp.js + category: security + technology: + - javascript + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: LOW + languages: + - javascript + - typescript + severity: WARNING + mode: taint + pattern-sources: + - patterns: + - pattern-inside: | + function ... (...,$ARG,...) {...} + - focus-metavariable: $ARG + pattern-sinks: + - patterns: + - pattern-either: + - pattern: new RegExp($ARG, ...) + - pattern: RegExp($ARG, ...) + - pattern-not: RegExp("...", ...) + - pattern-not: new RegExp("...", ...) + - pattern-not: RegExp(/.../, ...) + - pattern-not: new RegExp(/.../, ...) +- id: javascript.lang.security.audit.detect-non-literal-require.detect-non-literal-require + message: >- + Detected the use of require(variable). Calling require with a non-literal + argument might allow an attacker to load and run arbitrary code, or + access arbitrary files. + metadata: + cwe: + - "CWE-95: Improper Neutralization of Directives in Dynamically Evaluated Code ('Eval Injection')" + owasp: + - A03:2021 - Injection + source-rule-url: https://github.com/nodesecurity/eslint-plugin-security/blob/master/rules/detect-non-literal-require.js + references: + - https://github.com/nodesecurity/eslint-plugin-security/blob/master/rules/detect-non-literal-require.js + category: security + technology: + - javascript + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: LOW + languages: + - javascript + - typescript + severity: WARNING + mode: taint + pattern-sources: + - patterns: + - pattern-inside: function ... (..., $ARG,...) {...} + - focus-metavariable: $ARG + pattern-sinks: + - pattern: require(...) +- id: javascript.lang.security.audit.detect-redos.detect-redos + message: >- + Detected the use of a regular expression `$REDOS` which appears to be vulnerable to a Regular expression Denial-of-Service (ReDoS). For this reason, it is recommended to review the regex and ensure it is not vulnerable to catastrophic backtracking, and if possible use a library which offers default safety against ReDoS vulnerabilities. + metadata: + owasp: + - A05:2021 - Security Misconfiguration + - A06:2017 - Security Misconfiguration + cwe: + - "CWE-1333: Inefficient Regular Expression Complexity" + references: + - https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS + - https://www.regular-expressions.info/redos.html + category: security + technology: + - javascript + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: LOW + languages: + - javascript + - typescript + severity: WARNING + patterns: + - pattern-either: + - pattern: | + new RegExp(/$REDOS/,...) + - pattern: | + new RegExp("$REDOS",...) + - pattern: | + /$REDOS/.test(...) + - pattern: | + "$REDOS".test(...) + - pattern: | + $X.match(/$REDOS/) + - pattern: | + $X.match("$REDOS") + - metavariable-analysis: + analyzer: redos + metavariable: $REDOS +- id: javascript.lang.security.audit.hardcoded-hmac-key.hardcoded-hmac-key + message: >- + Detected a hardcoded hmac key. Avoid hardcoding secrets and consider using an alternate + option such as reading the secret from a config file or using an environment variable. + options: + interfile: true + metadata: + interfile: true + category: security + technology: + - crypto + - hmac + references: + - https://rules.sonarsource.com/javascript/RSPEC-2068 + - https://cheatsheetseries.owasp.org/cheatsheets/Cryptographic_Storage_Cheat_Sheet.html#key-management + owasp: + - A07:2021 - Identification and Authentication Failures + cwe: + - 'CWE-798: Use of Hard-coded Credentials' + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: + - javascript + - typescript + severity: WARNING + pattern-either: + - pattern: $CRYPTO.createHmac($ALGO, '...') + - patterns: + - pattern-inside: | + const $SECRET = '...' + ... + - pattern: $CRYPTO.createHmac($ALGO, $SECRET) +- id: javascript.lang.security.audit.incomplete-sanitization.incomplete-sanitization + message: >- + `$STR.replace` method will only replace the first occurrence when used with a string argument ($CHAR). + If this method is used for escaping of dangerous data then there is a possibility for a bypass. + Try to use sanitization library instead or use a Regex with a global flag. + metadata: + cwe: + - 'CWE-116: Improper Encoding or Escaping of Output' + category: security + technology: + - javascript + owasp: + - A03:2021 - Injection + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + references: + - https://owasp.org/Top10/A03_2021-Injection + languages: + - javascript + - typescript + severity: WARNING + patterns: + - pattern: | + $STR.replace(($CHAR: string), ...) + - metavariable-regex: + metavariable: $CHAR + regex: ^[\"\']([\'\"\<\>\*\|\{\}\[\]\%\$]{1}|\\n|\\r|\\t|\\&)[\"\']$ +- id: javascript.lang.security.audit.md5-used-as-password.md5-used-as-password + message: >- + It looks like MD5 is used as a password hash. MD5 is not considered a + secure password hash because it can be cracked by an attacker in a short + amount of time. Use a suitable password hashing function such as bcrypt. + You can use the `bcrypt` node.js package. + metadata: + category: security + technology: + - crypto + - md5 + references: + - https://tools.ietf.org/id/draft-lvelvindron-tls-md5-sha1-deprecate-01.html + - https://security.stackexchange.com/questions/211/how-to-securely-hash-passwords + - https://github.com/returntocorp/semgrep-rules/issues/1609 + - https://www.npmjs.com/package/bcrypt + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + cwe: + - 'CWE-327: Use of a Broken or Risky Cryptographic Algorithm' + subcategory: + - vuln + likelihood: HIGH + impact: MEDIUM + confidence: LOW + languages: + - javascript + severity: WARNING + mode: taint + pattern-sources: + - pattern: $CRYPTO.createHash("md5") + pattern-sinks: + - patterns: + - pattern: $FUNCTION(...); + - metavariable-regex: + metavariable: $FUNCTION + regex: (?i)(.*password.*) +- id: javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal + message: >- + Detected possible user input going into a `path.join` or `path.resolve` + function. This could possibly lead to a path traversal vulnerability, + where the attacker can access arbitrary files stored in the file system. + Instead, be sure to sanitize or validate user input first. + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - "CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')" + category: security + references: + - https://owasp.org/www-community/attacks/Path_Traversal + technology: + - javascript + - node.js + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: HIGH + impact: MEDIUM + confidence: LOW + languages: + - javascript + - typescript + severity: WARNING + mode: taint + pattern-sources: + - patterns: + - focus-metavariable: $X + - pattern-either: + - pattern-inside: | + function ... (...,$X,...) {...} + - pattern-inside: | + function ... (...,{...,$X,...},...) {...} + pattern-sinks: + - patterns: + - focus-metavariable: $SINK + - pattern-either: + - pattern-inside: | + $PATH = require('path'); + ... + - pattern-inside: | + import $PATH from 'path'; + ... + - pattern-either: + - pattern: $PATH.join(...,$SINK,...) + - pattern: $PATH.resolve(...,$SINK,...) + - patterns: + - focus-metavariable: $SINK + - pattern-inside: | + import 'path'; + ... + - pattern-either: + - pattern-inside: path.join(...,$SINK,...) + - pattern-inside: path.resolve(...,$SINK,...) + pattern-sanitizers: + - pattern: $Y.replace(...) + - pattern: $Y.indexOf(...) + - pattern: | + function ... (...) { + ... + <... $Y.indexOf(...) ...> + ... + } + - patterns: + - pattern: $FUNC(...) + - metavariable-regex: + metavariable: $FUNC + regex: sanitize +- id: javascript.lang.security.audit.prototype-pollution.prototype-pollution-assignment.prototype-pollution-assignment + message: >- + Possibility of prototype polluting assignment detected. + By adding or modifying attributes of an object prototype, it is possible to create + attributes that exist on every object, + or replace critical attributes with malicious ones. + This can be problematic if the software depends on existence or non-existence + of certain attributes, or uses pre-defined + attributes of object prototype (such as hasOwnProperty, toString or valueOf). + Possible mitigations might be: freezing the object prototype, using an object + without prototypes (via Object.create(null) + ), blocking modifications of attributes that resolve to object prototype, using + Map instead of object. + metadata: + cwe: + - 'CWE-915: Improperly Controlled Modification of Dynamically-Determined Object Attributes' + owasp: + - A08:2021 - Software and Data Integrity Failures + category: security + references: + - https://github.com/HoLyVieR/prototype-pollution-nsec18/blob/master/paper/JavaScript_prototype_pollution_attack_in_NodeJS.pdf + technology: + - javascript + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: + - javascript + - typescript + severity: WARNING + patterns: + - pattern: | + $X[$B] = ... + - pattern-not: | + $X[$B] = '...' + - pattern-inside: | + $X = $SMTH[$A] + ... + - pattern-not-inside: | + if (<...'constructor' ...>) { + ... + } + ... + - pattern-not-inside: | + if (<...'__proto__' ...>) { + ... + } + ... + - pattern-not-inside: | + for(var $B = $S; ...; ...) {...} + - pattern-not-inside: | + for($B = $S; ...; ...) {...} + - pattern-not-inside: | + $X.forEach(function $NAME($OBJ, $B,...) {...}) + - metavariable-pattern: + patterns: + - pattern-not: '"..."' + - pattern-not: | + `...${...}...` + - pattern-not: | + ($A: float) + metavariable: $A + - metavariable-pattern: + patterns: + - pattern-not: '"..."' + - pattern-not: | + `...${...}...` + - pattern-not: | + ($B: float) + metavariable: $B +- id: javascript.lang.security.audit.prototype-pollution.prototype-pollution-loop.prototype-pollution-loop + message: >- + Possibility of prototype polluting function detected. + By adding or modifying attributes of an object prototype, it is possible to create + attributes that exist on every object, + or replace critical attributes with malicious ones. + This can be problematic if the software depends on existence or non-existence + of certain attributes, or uses pre-defined + attributes of object prototype (such as hasOwnProperty, toString or valueOf). + Possible mitigations might be: freezing the object prototype, using an object + without prototypes (via Object.create(null) + ), blocking modifications of attributes that resolve to object prototype, using + Map instead of object. + metadata: + cwe: + - 'CWE-915: Improperly Controlled Modification of Dynamically-Determined Object Attributes' + category: security + references: + - https://github.com/HoLyVieR/prototype-pollution-nsec18/blob/master/paper/JavaScript_prototype_pollution_attack_in_NodeJS.pdf + technology: + - typescript + owasp: + - A08:2021 - Software and Data Integrity Failures + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: + - typescript + - javascript + severity: WARNING + patterns: + - pattern-either: + - pattern: | + $SMTH = $SMTH[$A] + - pattern: | + $SMTH = $SMTH[$A] = ... + - pattern: | + $SMTH = $SMTH[$A] && $Z + - pattern: | + $SMTH = $SMTH[$A] || $Z + - pattern-either: + - pattern-inside: | + for(...) { + ... + } + - pattern-inside: | + while(...) { + ... + } + - pattern-inside: | + $X.forEach(function $NAME(...) { + ... + }) + - pattern-not-inside: | + for(var $A = $S; ...; ...) {...} + - pattern-not-inside: | + for($A = $S; ...; ...) {...} + - pattern-not-inside: | + $X.forEach(function $NAME($OBJ, $A,...) {...}) + - metavariable-pattern: + patterns: + - pattern-not: '"..."' + - pattern-not: | + `...${...}...` + - pattern-not: | + ($A: float) + metavariable: $A +- id: javascript.lang.security.audit.spawn-shell-true.spawn-shell-true + message: >- + Found '$SPAWN' with '{shell: $SHELL}'. This is dangerous because this call will + spawn + the command using a shell process. Doing so propagates current shell settings + and variables, which + makes it much easier for a malicious actor to execute commands. Use '{shell: false}' + instead. + metadata: + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + cwe: + - "CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')" + category: security + technology: + - javascript + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + references: + - https://owasp.org/Top10/A03_2021-Injection + languages: + - javascript + - typescript + severity: ERROR + patterns: + - pattern-either: + - pattern: | + spawn(...,{shell: $SHELL}) + - pattern: | + spawnSync(...,{shell: $SHELL}) + - pattern: | + $CP.spawn(...,{shell: $SHELL}) + - pattern: | + $CP.spawnSync(...,{shell: $SHELL}) + - pattern-not: | + spawn(...,{shell: false}) + - pattern-not: | + spawnSync(...,{shell: false}) + - pattern-not: | + $CP.spawn(...,{shell: false}) + - pattern-not: | + $CP.spawnSync(...,{shell: false}) +- id: javascript.lang.security.audit.sqli.node-knex-sqli.node-knex-sqli + message: >- + Detected SQL statement that is tainted by `$REQ` object. This could + lead to SQL injection if the variable is user-controlled and not properly + sanitized. In order to prevent SQL injection, it is recommended to + use parameterized queries or prepared statements. An example of + parameterized queries like so: `knex.raw('SELECT $1 from table', + [userinput])` can help prevent SQLi. + metadata: + confidence: MEDIUM + references: + - https://knexjs.org/#Builder-fromRaw + - https://knexjs.org/#Builder-whereRaw + - https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html + category: security + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + cwe: + - "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')" + technology: + - express + - nodejs + - knex + license: Commons Clause License Condition v1.0[LGPL-2.1-only] + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: HIGH + impact: MEDIUM + languages: + - javascript + - typescript + severity: WARNING + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - pattern-inside: function ... ($REQ, $RES) {...} + - pattern-inside: function ... ($REQ, $RES, $NEXT) {...} + - patterns: + - pattern-either: + - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES) {...}) + - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES, $NEXT) {...}) + - metavariable-regex: + metavariable: $METHOD + regex: ^(get|post|put|head|delete|options) + - pattern-either: + - pattern: $REQ.query + - pattern: $REQ.body + - pattern: $REQ.params + - pattern: $REQ.cookies + - pattern: $REQ.headers + - pattern: $REQ.files.$ANYTHING.data.toString('utf8') + - pattern: $REQ.files.$ANYTHING['data'].toString('utf8') + - patterns: + - pattern-either: + - pattern-inside: | + ({ $REQ }: Request,$RES: Response, $NEXT: NextFunction) => + {...} + - pattern-inside: | + ({ $REQ }: Request,$RES: Response) => {...} + - focus-metavariable: $REQ + - pattern-either: + - pattern: params + - pattern: query + - pattern: cookies + - pattern: headers + - pattern: body + - pattern: files.$ANYTHING.data.toString('utf8') + - pattern: files.$ANYTHING['data'].toString('utf8') + pattern-sinks: + - patterns: + - focus-metavariable: $QUERY + - pattern-either: + - pattern-inside: $KNEX.fromRaw($QUERY, ...) + - pattern-inside: $KNEX.whereRaw($QUERY, ...) + - pattern-inside: $KNEX.raw($QUERY, ...) + - pattern-either: + - pattern-inside: | + require('knex') + ... + - pattern-inside: | + import 'knex' + ... + pattern-sanitizers: + - patterns: + - pattern: parseInt(...) +- id: javascript.lang.security.audit.sqli.node-mssql-sqli.node-mssql-sqli + message: >- + Detected string concatenation with a non-literal variable in a + `mssql` JS SQL statement. This could lead to SQL injection if the variable is + user-controlled + and not properly sanitized. In order to prevent SQL injection, + use parameterized queries or prepared statements instead. + You can use parameterized statements like so: + `$REQ.input('USER_ID', mssql.Int, id);` + metadata: + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + cwe: + - "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')" + category: security + technology: + - mssql + license: Commons Clause License Condition v1.0[LGPL-2.1-only] + references: + - https://www.npmjs.com/package/mssql + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: HIGH + impact: MEDIUM + confidence: LOW + languages: + - javascript + - typescript + severity: WARNING + mode: taint + pattern-sources: + - patterns: + - pattern-inside: | + function ... (...,$FUNC,...) { + ... + } + - focus-metavariable: $FUNC + pattern-sinks: + - patterns: + - pattern-either: + - pattern-inside: | + require('mssql'); + ... + - pattern-inside: | + import 'mssql'; + ... + - pattern-inside: | + $REQ = $POOL.request(...) + ... + - pattern: | + $REQ.query($QUERY,...) + - focus-metavariable: $QUERY +- id: javascript.lang.security.audit.sqli.node-mysql-sqli.node-mysql-sqli + message: >- + Detected a `$IMPORT` SQL statement that comes from a function argument. This could lead to SQL injection + if the variable is user-controlled and is not + properly sanitized. In order to prevent SQL injection, it is recommended to + use parameterized queries or prepared statements. + metadata: + references: + - https://www.npmjs.com/package/mysql2 + - https://www.npmjs.com/package/mysql + - https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html + category: security + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + cwe: + - "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')" + confidence: LOW + technology: + - mysql + - mysql2 + - javascript + - nodejs + license: Commons Clause License Condition v1.0[LGPL-2.1-only] + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: HIGH + impact: MEDIUM + languages: + - javascript + - typescript + severity: WARNING + mode: taint + pattern-sources: + - patterns: + - pattern-inside: function ... (..., $Y,...) {...} + - pattern: $Y + - pattern-not-inside: | + function ... (..., $Y: number,...) {...} + - pattern-not-inside: $Y.query + - pattern-not-inside: $Y.body + - pattern-not-inside: $Y.params + - pattern-not-inside: $Y.cookies + - pattern-not-inside: $Y.headers + pattern-sinks: + - patterns: + - focus-metavariable: $QUERY + - pattern-either: + - pattern-inside: $POOL.query($QUERY, ...) + - pattern-inside: $POOL.execute($QUERY, ...) + - pattern-either: + - pattern-inside: | + import $S from "$IMPORT" + ... + - pattern-inside: | + import { ... } from "$IMPORT" + ... + - pattern-inside: | + import * as $S from "$IMPORT" + ... + - pattern-inside: | + require("$IMPORT") + ... + - metavariable-regex: + metavariable: $IMPORT + regex: (mysql|mysql2) + pattern-sanitizers: + - patterns: + - pattern: parseInt(...) +- id: javascript.lang.security.audit.sqli.node-postgres-sqli.node-postgres-sqli + message: >- + Detected string concatenation with a non-literal variable in a node-postgres + JS SQL statement. This could lead to SQL injection if the variable is user-controlled + and not properly sanitized. In order to prevent SQL injection, + use parameterized queries or prepared statements instead. + You can use parameterized statements like so: + `client.query('SELECT $1 from table', [userinput])` + metadata: + owasp: + - A08:2021 - Software and Data Integrity Failures + cwe: + - 'CWE-915: Improperly Controlled Modification of Dynamically-Determined Object Attributes' + references: + - https://node-postgres.com/features/queries + category: security + technology: + - node-postgres + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: LOW + languages: + - javascript + - typescript + severity: WARNING + mode: taint + pattern-sources: + - patterns: + - pattern-inside: | + function ... (...,$FUNC,...) { + ... + } + - focus-metavariable: $FUNC + - pattern-not-inside: | + $F. ... .$SOURCE(...) + pattern-sinks: + - patterns: + - pattern-either: + - pattern-inside: | + const { $CLIENT } = require('pg') + ... + - pattern-inside: | + var { $CLIENT } = require('pg') + ... + - pattern-inside: | + let { $CLIENT } = require('pg') + ... + - pattern-either: + - pattern-inside: | + $DB = new $CLIENT(...) + ... + - pattern-inside: | + $NEWPOOL = new $CLIENT(...) + ... + $NEWPOOL.connect((..., $DB, ...) => { + ... + }) + - pattern: $DB.query($QUERY,...) + - focus-metavariable: $QUERY +- id: javascript.lang.security.audit.unknown-value-with-script-tag.unknown-value-with-script-tag + message: >- + Cannot determine what '$UNK' is and it is used with a ' + - pattern: '{{ ... }}' + - pattern-not-inside: nonce = '...' + - pattern-not-inside: nonce = "..." + paths: + include: + - '*.html' + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + references: + - https://adamj.eu/tech/2020/02/18/safely-including-data-for-javascript-in-a-django-template/?utm_campaign=Django%2BNewsletter&utm_medium=rss&utm_source=Django_Newsletter_12A + - https://www.veracode.com/blog/secure-development/nodejs-template-engines-why-default-encoders-are-not-enough + - https://github.com/ESAPI/owasp-esapi-js + category: security + technology: + - django + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW +- id: python.django.security.django-no-csrf-token.django-no-csrf-token + patterns: + - pattern: "..." + - pattern-either: + - pattern: | +
...
+ - pattern: | +
...
+ - pattern: | +
...
+ - metavariable-regex: + metavariable: $METHOD + regex: (?i)(post|put|delete|patch) + - pattern-not-inside: "...{% csrf_token %}..." + - pattern-not-inside: "...{{ $VAR.csrf_token }}..." + message: Manually-created forms in django templates should specify a csrf_token to prevent CSRF attacks + languages: [generic] + severity: WARNING + metadata: + category: security + cwe: "CWE-352: Cross-Site Request Forgery (CSRF)" + references: + - https://docs.djangoproject.com/en/4.2/howto/csrf/ + confidence: MEDIUM + likelihood: MEDIUM + impact: MEDIUM + subcategory: + - guardrail + technology: + - django + paths: + include: + - "*.html" +- id: python.django.security.django-using-request-post-after-is-valid.django-using-request-post-after-is-valid + patterns: + - pattern-inside: | + def $FUNC(request, ...): + ... + - pattern-inside: | + if $FORM.is_valid(): + ... + - pattern-either: + - pattern: request.POST[...] + - pattern: request.POST.get(...) + message: Use $FORM.cleaned_data[] instead of request.POST[] after form.is_valid() has been executed to only access sanitized data + languages: [python] + severity: WARNING + metadata: + category: security + cwe: "CWE-20: Improper Input Validation" + references: + - https://docs.djangoproject.com/en/4.2/ref/forms/api/#accessing-clean-data + confidence: MEDIUM + likelihood: MEDIUM + impact: MEDIUM + subcategory: + - guardrail + technology: + - django +- id: python.django.security.globals-as-template-context.globals-as-template-context + languages: + - python + message: >- + Using 'globals()' as a context to 'render(...)' is extremely dangerous. + This exposes Python functions to the template that were not meant to be exposed. + An attacker could use these functions to execute code that was not intended to run + and could compromise the application. (This is server-side template injection (SSTI)). + Do not use 'globals()'. Instead, specify each variable in a dictionary or + 'django.template.Context' object, like '{"var1": "hello"}' and use that instead. + metadata: + category: security + cwe: + - "CWE-96: Improper Neutralization of Directives in Statically Saved Code ('Static Code Injection')" + owasp: + - A03:2021 - Injection + references: + - https://docs.djangoproject.com/en/3.2/ref/settings/#templates + - https://docs.djangoproject.com/en/3.2/topics/templates/#django.template.backends.django.DjangoTemplates + - https://docs.djangoproject.com/en/3.2/ref/templates/api/#rendering-a-context + technology: + - django + subcategory: + - audit + likelihood: LOW + impact: HIGH + confidence: LOW + pattern-either: + - pattern: django.shortcuts.render(..., globals(...), ...) + - pattern: django.template.Template.render(..., globals(...), ...) + - patterns: + - pattern-inside: | + $CONTEXT = globals(...) + ... + - pattern-either: + - pattern: django.shortcuts.render(..., $CONTEXT, ...) + - pattern: django.template.Template.render(..., $CONTEXT, ...) + severity: ERROR +- id: python.django.security.hashids-with-django-secret.hashids-with-django-secret + languages: + - python + message: >- + The Django secret key is used as salt in HashIDs. The HashID mechanism is not secure. + By observing sufficient HashIDs, the salt used to construct them can be recovered. + This means the Django secret key can be obtained by attackers, through the HashIDs. + metadata: + category: security + subcategory: + - vuln + cwe: + - "CWE-327: Use of a Broken or Risky Cryptographic Algorithm" + owasp: + - A02:2021 – Cryptographic Failures + references: + - https://docs.djangoproject.com/en/4.2/ref/settings/#std-setting-SECRET_KEY + - http://carnage.github.io/2015/08/cryptanalysis-of-hashids + technology: + - django + likelihood: LOW + impact: HIGH + confidence: HIGH + pattern-either: + - pattern: hashids.Hashids(..., salt=django.conf.settings.SECRET_KEY, ...) + - pattern: hashids.Hashids(django.conf.settings.SECRET_KEY, ...) + severity: ERROR +- id: python.django.security.injection.code.globals-misuse-code-execution.globals-misuse-code-execution + message: >- + Found request data as an index to 'globals()'. This is extremely + dangerous because it allows an attacker to execute arbitrary code + on the system. Refactor your code not to use 'globals()'. + metadata: + cwe: + - "CWE-96: Improper Neutralization of Directives in Statically Saved Code ('Static Code Injection')" + owasp: + - A03:2021 - Injection + references: + - https://github.com/mpirnat/lets-be-bad-guys/blob/d92768fb3ade32956abd53bd6bb06e19d634a084/badguys/vulnerable/views.py#L181-L186 + category: security + technology: + - django + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + languages: [python] + severity: WARNING + patterns: + - pattern-inside: | + def $FUNC(...): + ... + - pattern-either: + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = globals().get($DATA, ...) + ... + $INTERM(...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = globals().get("..." % $DATA, ...) + ... + $INTERM(...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = globals().get(f"...{$DATA}...", ...) + ... + $INTERM(...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = globals().get("...".format(..., $DATA, ...), ...) + ... + $INTERM(...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = globals()[$DATA] + ... + $INTERM(...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = globals()["..." % $DATA] + ... + $INTERM(...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = globals()[f"...{$DATA}..."] + ... + $INTERM(...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = globals()["...".format(..., $DATA, ...)] + ... + $INTERM(...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = globals().get($DATA, ...) + ... + $INTERM(...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = globals().get("..." % $DATA, ...) + ... + $INTERM(...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = globals().get(f"...{$DATA}...", ...) + ... + $INTERM(...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = globals().get("...".format(..., $DATA, ...), ...) + ... + $INTERM(...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = globals()[$DATA] + ... + $INTERM(...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = globals()["..." % $DATA] + ... + $INTERM(...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = globals()[f"...{$DATA}..."] + ... + $INTERM(...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = globals()["...".format(..., $DATA, ...)] + ... + $INTERM(...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = globals().get($DATA, ...) + ... + $INTERM(...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = globals().get("..." % $DATA, ...) + ... + $INTERM(...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = globals().get(f"...{$DATA}...", ...) + ... + $INTERM(...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = globals().get("...".format(..., $DATA, ...), ...) + ... + $INTERM(...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = globals()[$DATA] + ... + $INTERM(...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = globals()["..." % $DATA] + ... + $INTERM(...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = globals()[f"...{$DATA}..."] + ... + $INTERM(...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = globals()["...".format(..., $DATA, ...)] + ... + $INTERM(...) + - pattern: | + $DATA = request.$W + ... + $INTERM = globals().get($DATA, ...) + ... + $INTERM(...) + - pattern: | + $DATA = request.$W + ... + $INTERM = globals().get("..." % $DATA, ...) + ... + $INTERM(...) + - pattern: | + $DATA = request.$W + ... + $INTERM = globals().get(f"...{$DATA}...", ...) + ... + $INTERM(...) + - pattern: | + $DATA = request.$W + ... + $INTERM = globals().get("...".format(..., $DATA, ...), ...) + ... + $INTERM(...) + - pattern: | + $DATA = request.$W + ... + $INTERM = globals()[$DATA] + ... + $INTERM(...) + - pattern: | + $DATA = request.$W + ... + $INTERM = globals()["..." % $DATA] + ... + $INTERM(...) + - pattern: | + $DATA = request.$W + ... + $INTERM = globals()[f"...{$DATA}..."] + ... + $INTERM(...) + - pattern: | + $DATA = request.$W + ... + $INTERM = globals()["...".format(..., $DATA, ...)] + ... + $INTERM(...) +- id: python.django.security.injection.code.user-eval-format-string.user-eval-format-string + message: >- + Found user data in a call to 'eval'. This is extremely dangerous because + it can enable an attacker to execute remote code. See + https://owasp.org/www-community/attacks/Code_Injection for more information. + metadata: + cwe: + - "CWE-95: Improper Neutralization of Directives in Dynamically Evaluated Code ('Eval Injection')" + owasp: + - A03:2021 - Injection + references: + - https://nedbatchelder.com/blog/201206/eval_really_is_dangerous.html + category: security + technology: + - django + subcategory: + - vuln + likelihood: MEDIUM + impact: HIGH + confidence: MEDIUM + patterns: + - pattern-inside: | + def $F(...): + ... + - pattern-either: + - pattern: eval(..., $STR % request.$W.get(...), ...) + - pattern: | + $V = request.$W.get(...) + ... + eval(..., $STR % $V, ...) + - pattern: | + $V = request.$W.get(...) + ... + $S = $STR % $V + ... + eval(..., $S, ...) + - pattern: eval(..., "..." % request.$W(...), ...) + - pattern: | + $V = request.$W(...) + ... + eval(..., $STR % $V, ...) + - pattern: | + $V = request.$W(...) + ... + $S = $STR % $V + ... + eval(..., $S, ...) + - pattern: eval(..., $STR % request.$W[...], ...) + - pattern: | + $V = request.$W[...] + ... + eval(..., $STR % $V, ...) + - pattern: | + $V = request.$W[...] + ... + $S = $STR % $V + ... + eval(..., $S, ...) + - pattern: eval(..., $STR.format(..., request.$W.get(...), ...), ...) + - pattern: | + $V = request.$W.get(...) + ... + eval(..., $STR.format(..., $V, ...), ...) + - pattern: | + $V = request.$W.get(...) + ... + $S = $STR.format(..., $V, ...) + ... + eval(..., $S, ...) + - pattern: eval(..., $STR.format(..., request.$W(...), ...), ...) + - pattern: | + $V = request.$W(...) + ... + eval(..., $STR.format(..., $V, ...), ...) + - pattern: | + $V = request.$W(...) + ... + $S = $STR.format(..., $V, ...) + ... + eval(..., $S, ...) + - pattern: eval(..., $STR.format(..., request.$W[...], ...), ...) + - pattern: | + $V = request.$W[...] + ... + eval(..., $STR.format(..., $V, ...), ...) + - pattern: | + $V = request.$W[...] + ... + $S = $STR.format(..., $V, ...) + ... + eval(..., $S, ...) + - pattern: | + $V = request.$W.get(...) + ... + eval(..., f"...{$V}...", ...) + - pattern: | + $V = request.$W.get(...) + ... + $S = f"...{$V}..." + ... + eval(..., $S, ...) + - pattern: | + $V = request.$W(...) + ... + eval(..., f"...{$V}...", ...) + - pattern: | + $V = request.$W(...) + ... + $S = f"...{$V}..." + ... + eval(..., $S, ...) + - pattern: | + $V = request.$W[...] + ... + eval(..., f"...{$V}...", ...) + - pattern: | + $V = request.$W[...] + ... + $S = f"...{$V}..." + ... + eval(..., $S, ...) + languages: [python] + severity: WARNING +- id: python.django.security.injection.code.user-eval.user-eval + message: >- + Found user data in a call to 'eval'. This is extremely dangerous because it can enable an attacker + to + execute arbitrary remote code on the system. Instead, refactor your code to not use 'eval' + and instead use a safe library for the specific functionality you need. + metadata: + cwe: + - "CWE-95: Improper Neutralization of Directives in Dynamically Evaluated Code ('Eval Injection')" + owasp: + - A03:2021 - Injection + references: + - https://nedbatchelder.com/blog/201206/eval_really_is_dangerous.html + - https://owasp.org/www-community/attacks/Code_Injection + category: security + technology: + - django + subcategory: + - vuln + likelihood: MEDIUM + impact: HIGH + confidence: MEDIUM + patterns: + - pattern-inside: | + def $F(...): + ... + - pattern-either: + - pattern: eval(..., request.$W.get(...), ...) + - pattern: | + $V = request.$W.get(...) + ... + eval(..., $V, ...) + - pattern: eval(..., request.$W(...), ...) + - pattern: | + $V = request.$W(...) + ... + eval(..., $V, ...) + - pattern: eval(..., request.$W[...], ...) + - pattern: | + $V = request.$W[...] + ... + eval(..., $V, ...) + languages: [python] + severity: WARNING +- id: python.django.security.injection.code.user-exec-format-string.user-exec-format-string + message: >- + Found user data in a call to 'exec'. This is extremely dangerous because it can enable an attacker + to + execute arbitrary remote code on the system. Instead, refactor your code to not use 'eval' and + instead use a safe library for the specific functionality you need. + metadata: + cwe: + - "CWE-95: Improper Neutralization of Directives in Dynamically Evaluated Code ('Eval Injection')" + owasp: + - A03:2021 - Injection + category: security + technology: + - django + references: + - https://owasp.org/www-community/attacks/Code_Injection + subcategory: + - vuln + likelihood: MEDIUM + impact: HIGH + confidence: MEDIUM + patterns: + - pattern-inside: | + def $F(...): + ... + - pattern-either: + - pattern: exec(..., $STR % request.$W.get(...), ...) + - pattern: | + $V = request.$W.get(...) + ... + exec(..., $STR % $V, ...) + - pattern: | + $V = request.$W.get(...) + ... + $S = $STR % $V + ... + exec(..., $S, ...) + - pattern: exec(..., "..." % request.$W(...), ...) + - pattern: | + $V = request.$W(...) + ... + exec(..., $STR % $V, ...) + - pattern: | + $V = request.$W(...) + ... + $S = $STR % $V + ... + exec(..., $S, ...) + - pattern: exec(..., $STR % request.$W[...], ...) + - pattern: | + $V = request.$W[...] + ... + exec(..., $STR % $V, ...) + - pattern: | + $V = request.$W[...] + ... + $S = $STR % $V + ... + exec(..., $S, ...) + - pattern: exec(..., $STR.format(..., request.$W.get(...), ...), ...) + - pattern: | + $V = request.$W.get(...) + ... + exec(..., $STR.format(..., $V, ...), ...) + - pattern: | + $V = request.$W.get(...) + ... + $S = $STR.format(..., $V, ...) + ... + exec(..., $S, ...) + - pattern: exec(..., $STR.format(..., request.$W(...), ...), ...) + - pattern: | + $V = request.$W(...) + ... + exec(..., $STR.format(..., $V, ...), ...) + - pattern: | + $V = request.$W(...) + ... + $S = $STR.format(..., $V, ...) + ... + exec(..., $S, ...) + - pattern: exec(..., $STR.format(..., request.$W[...], ...), ...) + - pattern: | + $V = request.$W[...] + ... + exec(..., $STR.format(..., $V, ...), ...) + - pattern: | + $V = request.$W[...] + ... + $S = $STR.format(..., $V, ...) + ... + exec(..., $S, ...) + - pattern: | + $V = request.$W.get(...) + ... + exec(..., f"...{$V}...", ...) + - pattern: | + $V = request.$W.get(...) + ... + $S = f"...{$V}..." + ... + exec(..., $S, ...) + - pattern: | + $V = request.$W(...) + ... + exec(..., f"...{$V}...", ...) + - pattern: | + $V = request.$W(...) + ... + $S = f"...{$V}..." + ... + exec(..., $S, ...) + - pattern: | + $V = request.$W[...] + ... + exec(..., f"...{$V}...", ...) + - pattern: | + $V = request.$W[...] + ... + $S = f"...{$V}..." + ... + exec(..., $S, ...) + - pattern: exec(..., base64.decodestring($S.format(..., request.$W.get(...), ...), ...), ...) + - pattern: exec(..., base64.decodestring($S % request.$W.get(...), ...), ...) + - pattern: exec(..., base64.decodestring(f"...{request.$W.get(...)}...", ...), ...) + - pattern: exec(..., base64.decodestring(request.$W.get(...), ...), ...) + - pattern: exec(..., base64.decodestring(bytes($S.format(..., request.$W.get(...), ...), ...), ...), + ...) + - pattern: exec(..., base64.decodestring(bytes($S % request.$W.get(...), ...), ...), ...) + - pattern: exec(..., base64.decodestring(bytes(f"...{request.$W.get(...)}...", ...), ...), ...) + - pattern: exec(..., base64.decodestring(bytes(request.$W.get(...), ...), ...), ...) + - pattern: | + $DATA = request.$W.get(...) + ... + exec(..., base64.decodestring($DATA, ...), ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = base64.decodestring($DATA, ...) + ... + exec(..., $INTERM, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + exec(..., base64.decodestring(bytes($DATA, ...), ...), ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = base64.decodestring(bytes($DATA, ...), ...) + ... + exec(..., $INTERM, ...) + - pattern: | + $DATA = request.$W(...) + ... + exec(..., base64.decodestring($DATA, ...), ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = base64.decodestring($DATA, ...) + ... + exec(..., $INTERM, ...) + - pattern: | + $DATA = request.$W(...) + ... + exec(..., base64.decodestring(bytes($DATA, ...), ...), ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = base64.decodestring(bytes($DATA, ...), ...) + ... + exec(..., $INTERM, ...) + - pattern: | + $DATA = request.$W[...] + ... + exec(..., base64.decodestring($DATA, ...), ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = base64.decodestring($DATA, ...) + ... + exec(..., $INTERM, ...) + - pattern: | + $DATA = request.$W[...] + ... + exec(..., base64.decodestring(bytes($DATA, ...), ...), ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = base64.decodestring(bytes($DATA, ...), ...) + ... + exec(..., $INTERM, ...) + - pattern: | + $DATA = request.$W + ... + exec(..., base64.decodestring($DATA, ...), ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = base64.decodestring($DATA, ...) + ... + exec(..., $INTERM, ...) + - pattern: | + $DATA = request.$W + ... + exec(..., base64.decodestring(bytes($DATA, ...), ...), ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = base64.decodestring(bytes($DATA, ...), ...) + ... + exec(..., $INTERM, ...) + languages: [python] + severity: WARNING +- id: python.django.security.injection.code.user-exec.user-exec + message: >- + Found user data in a call to 'exec'. This is extremely dangerous because it can enable an attacker + to + execute arbitrary remote code on the system. Instead, refactor your code to not use 'eval' and + instead use a safe library for the specific functionality you need. + metadata: + cwe: + - "CWE-95: Improper Neutralization of Directives in Dynamically Evaluated Code ('Eval Injection')" + owasp: + - A03:2021 - Injection + category: security + technology: + - django + references: + - https://owasp.org/www-community/attacks/Code_Injection + subcategory: + - vuln + likelihood: MEDIUM + impact: HIGH + confidence: MEDIUM + patterns: + - pattern-inside: | + def $F(...): + ... + - pattern-either: + - pattern: exec(..., request.$W.get(...), ...) + - pattern: | + $V = request.$W.get(...) + ... + exec(..., $V, ...) + - pattern: exec(..., request.$W(...), ...) + - pattern: | + $V = request.$W(...) + ... + exec(..., $V, ...) + - pattern: exec(..., request.$W[...], ...) + - pattern: | + $V = request.$W[...] + ... + exec(..., $V, ...) + - pattern: | + loop = asyncio.get_running_loop() + ... + await loop.run_in_executor(None, exec, request.$W[...]) + - pattern: | + $V = request.$W[...] + ... + loop = asyncio.get_running_loop() + ... + await loop.run_in_executor(None, exec, $V) + - pattern: | + loop = asyncio.get_running_loop() + ... + await loop.run_in_executor(None, exec, request.$W.get(...)) + - pattern: | + $V = request.$W.get(...) + ... + loop = asyncio.get_running_loop() + ... + await loop.run_in_executor(None, exec, $V) + languages: [python] + severity: WARNING +- id: python.django.security.injection.command.command-injection-os-system.command-injection-os-system + message: Request data detected in os.system. This could be vulnerable to a command injection and should + be avoided. If this must be done, use the 'subprocess' module instead and pass the arguments as a + list. See https://owasp.org/www-community/attacks/Command_Injection for more information. + metadata: + cwe: + - "CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')" + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + references: + - https://owasp.org/www-community/attacks/Command_Injection + category: security + technology: + - django + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: HIGH + confidence: MEDIUM + languages: [python] + severity: ERROR + patterns: + - pattern-inside: | + def $FUNC(...): + ... + - pattern-either: + - pattern: os.system(..., request.$W.get(...), ...) + - pattern: os.system(..., $S.format(..., request.$W.get(...), ...), ...) + - pattern: os.system(..., $S % request.$W.get(...), ...) + - pattern: os.system(..., f"...{request.$W.get(...)}...", ...) + - pattern: | + $DATA = request.$W.get(...) + ... + os.system(..., $DATA, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = $DATA + ... + os.system(..., $INTERM, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + os.system(..., $STR.format(..., $DATA, ...), ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = $STR.format(..., $DATA, ...) + ... + os.system(..., $INTERM, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + os.system(..., $STR % $DATA, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = $STR % $DATA + ... + os.system(..., $INTERM, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + os.system(..., f"...{$DATA}...", ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = f"...{$DATA}..." + ... + os.system(..., $INTERM, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + os.system(..., $STR + $DATA, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = $STR + $DATA + ... + os.system(..., $INTERM, ...) + - pattern: $A = os.system(..., request.$W.get(...), ...) + - pattern: $A = os.system(..., $S.format(..., request.$W.get(...), ...), ...) + - pattern: $A = os.system(..., $S % request.$W.get(...), ...) + - pattern: $A = os.system(..., f"...{request.$W.get(...)}...", ...) + - pattern: return os.system(..., request.$W.get(...), ...) + - pattern: return os.system(..., $S.format(..., request.$W.get(...), ...), ...) + - pattern: return os.system(..., $S % request.$W.get(...), ...) + - pattern: return os.system(..., f"...{request.$W.get(...)}...", ...) + - pattern: os.system(..., request.$W(...), ...) + - pattern: os.system(..., $S.format(..., request.$W(...), ...), ...) + - pattern: os.system(..., $S % request.$W(...), ...) + - pattern: os.system(..., f"...{request.$W(...)}...", ...) + - pattern: | + $DATA = request.$W(...) + ... + os.system(..., $DATA, ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = $DATA + ... + os.system(..., $INTERM, ...) + - pattern: | + $DATA = request.$W(...) + ... + os.system(..., $STR.format(..., $DATA, ...), ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = $STR.format(..., $DATA, ...) + ... + os.system(..., $INTERM, ...) + - pattern: | + $DATA = request.$W(...) + ... + os.system(..., $STR % $DATA, ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = $STR % $DATA + ... + os.system(..., $INTERM, ...) + - pattern: | + $DATA = request.$W(...) + ... + os.system(..., f"...{$DATA}...", ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = f"...{$DATA}..." + ... + os.system(..., $INTERM, ...) + - pattern: | + $DATA = request.$W(...) + ... + os.system(..., $STR + $DATA, ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = $STR + $DATA + ... + os.system(..., $INTERM, ...) + - pattern: $A = os.system(..., request.$W(...), ...) + - pattern: $A = os.system(..., $S.format(..., request.$W(...), ...), ...) + - pattern: $A = os.system(..., $S % request.$W(...), ...) + - pattern: $A = os.system(..., f"...{request.$W(...)}...", ...) + - pattern: return os.system(..., request.$W(...), ...) + - pattern: return os.system(..., $S.format(..., request.$W(...), ...), ...) + - pattern: return os.system(..., $S % request.$W(...), ...) + - pattern: return os.system(..., f"...{request.$W(...)}...", ...) + - pattern: os.system(..., request.$W[...], ...) + - pattern: os.system(..., $S.format(..., request.$W[...], ...), ...) + - pattern: os.system(..., $S % request.$W[...], ...) + - pattern: os.system(..., f"...{request.$W[...]}...", ...) + - pattern: | + $DATA = request.$W[...] + ... + os.system(..., $DATA, ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = $DATA + ... + os.system(..., $INTERM, ...) + - pattern: | + $DATA = request.$W[...] + ... + os.system(..., $STR.format(..., $DATA, ...), ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = $STR.format(..., $DATA, ...) + ... + os.system(..., $INTERM, ...) + - pattern: | + $DATA = request.$W[...] + ... + os.system(..., $STR % $DATA, ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = $STR % $DATA + ... + os.system(..., $INTERM, ...) + - pattern: | + $DATA = request.$W[...] + ... + os.system(..., f"...{$DATA}...", ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = f"...{$DATA}..." + ... + os.system(..., $INTERM, ...) + - pattern: | + $DATA = request.$W[...] + ... + os.system(..., $STR + $DATA, ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = $STR + $DATA + ... + os.system(..., $INTERM, ...) + - pattern: $A = os.system(..., request.$W[...], ...) + - pattern: $A = os.system(..., $S.format(..., request.$W[...], ...), ...) + - pattern: $A = os.system(..., $S % request.$W[...], ...) + - pattern: $A = os.system(..., f"...{request.$W[...]}...", ...) + - pattern: return os.system(..., request.$W[...], ...) + - pattern: return os.system(..., $S.format(..., request.$W[...], ...), ...) + - pattern: return os.system(..., $S % request.$W[...], ...) + - pattern: return os.system(..., f"...{request.$W[...]}...", ...) + - pattern: os.system(..., request.$W, ...) + - pattern: os.system(..., $S.format(..., request.$W, ...), ...) + - pattern: os.system(..., $S % request.$W, ...) + - pattern: os.system(..., f"...{request.$W}...", ...) + - pattern: | + $DATA = request.$W + ... + os.system(..., $DATA, ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = $DATA + ... + os.system(..., $INTERM, ...) + - pattern: | + $DATA = request.$W + ... + os.system(..., $STR.format(..., $DATA, ...), ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = $STR.format(..., $DATA, ...) + ... + os.system(..., $INTERM, ...) + - pattern: | + $DATA = request.$W + ... + os.system(..., $STR % $DATA, ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = $STR % $DATA + ... + os.system(..., $INTERM, ...) + - pattern: | + $DATA = request.$W + ... + os.system(..., f"...{$DATA}...", ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = f"...{$DATA}..." + ... + os.system(..., $INTERM, ...) + - pattern: | + $DATA = request.$W + ... + os.system(..., $STR + $DATA, ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = $STR + $DATA + ... + os.system(..., $INTERM, ...) + - pattern: $A = os.system(..., request.$W, ...) + - pattern: $A = os.system(..., $S.format(..., request.$W, ...), ...) + - pattern: $A = os.system(..., $S % request.$W, ...) + - pattern: $A = os.system(..., f"...{request.$W}...", ...) + - pattern: return os.system(..., request.$W, ...) + - pattern: return os.system(..., $S.format(..., request.$W, ...), ...) + - pattern: return os.system(..., $S % request.$W, ...) + - pattern: return os.system(..., f"...{request.$W}...", ...) +- id: python.django.security.injection.command.subprocess-injection.subprocess-injection + languages: [python] + mode: taint + options: + symbolic_propagation: true + pattern-sources: + - patterns: + - pattern-inside: | + def $FUNC(..., $REQUEST, ...): + ... + - focus-metavariable: $REQUEST + - metavariable-pattern: + metavariable: $REQUEST + patterns: + - pattern: request + - pattern-not-inside: request.build_absolute_uri + pattern-sinks: + - patterns: + - pattern-either: + - patterns: + - pattern: subprocess.$FUNC(...) + - pattern-not: subprocess.$FUNC("...", ...) + - pattern-not: subprocess.$FUNC(["...", ...], ...) + - pattern-not-inside: | + $CMD = ["...", ...] + ... + subprocess.$FUNC($CMD, ...) + - patterns: + - pattern: subprocess.$FUNC(["$SHELL", "-c", ...], ...) + - metavariable-regex: + metavariable: $SHELL + regex: ^(sh|bash|ksh|csh|tcsh|zsh)$ + - patterns: + - pattern: subprocess.$FUNC(["$INTERPRETER", ...], ...) + - metavariable-regex: + metavariable: $INTERPRETER + regex: ^(python|python\d)$ + pattern-sanitizers: + - patterns: + - pattern: $DICT[$KEY] + - focus-metavariable: $KEY + severity: ERROR + message: >- + Detected user input entering a `subprocess` call unsafely. This could + result in a command injection vulnerability. An attacker could use this + vulnerability to execute arbitrary commands on the host, which allows + them to download malware, scan sensitive data, or run any command they + wish on the server. Do not let users choose the command to run. In general, + prefer to use Python API versions of system commands. If you must use subprocess, + use a dictionary to allowlist a set of commands. + metadata: + category: security + technology: + - flask + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + cwe: + - "CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')" + references: + - https://semgrep.dev/docs/cheat-sheets/python-command-injection/ + confidence: HIGH + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: HIGH +- id: python.django.security.injection.csv-writer-injection.csv-writer-injection + languages: + - python + message: Detected user input into a generated CSV file using the built-in `csv` module. If user data + is used to generate the data in this file, it is possible that an attacker could inject a formula + when the CSV is imported into a spreadsheet application that runs an attacker script, which could + steal data from the importing user or, at worst, install malware on the user's computer. `defusedcsv` + is a drop-in replacement with the same API that will attempt to mitigate formula injection attempts. + You can use `defusedcsv` instead of `csv` to safely generate CSVs. + metadata: + category: security + confidence: MEDIUM + cwe: + - 'CWE-1236: Improper Neutralization of Formula Elements in a CSV File' + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + references: + - https://github.com/raphaelm/defusedcsv + - https://owasp.org/www-community/attacks/CSV_Injection + - https://web.archive.org/web/20220516052229/https://www.contextis.com/us/blog/comma-separated-vulnerabilities + technology: + - django + - python + subcategory: + - vuln + impact: MEDIUM + likelihood: MEDIUM + mode: taint + pattern-sinks: + - patterns: + - pattern-inside: | + $WRITER = csv.writer(...) + + ... + + $WRITER.$WRITE(...) + - pattern: $WRITER.$WRITE(...) + - metavariable-regex: + metavariable: $WRITE + regex: ^(writerow|writerows|writeheader)$ + pattern-sources: + - patterns: + - pattern-inside: | + def $FUNC(..., $REQUEST, ...): + ... + - focus-metavariable: $REQUEST + - metavariable-pattern: + metavariable: $REQUEST + patterns: + - pattern: request + - pattern-not-inside: request.build_absolute_uri + severity: ERROR +- id: python.django.security.injection.email.xss-html-email-body.xss-html-email-body + message: >- + Found request data in an EmailMessage that is set to use HTML. + This is dangerous because HTML emails are susceptible to XSS. + An attacker could inject data into this HTML email, causing XSS. + metadata: + cwe: + - "CWE-74: Improper Neutralization of Special Elements in Output Used by a Downstream Component ('Injection')" + owasp: + - A03:2021 - Injection + references: + - https://www.damonkohler.com/2008/12/email-injection.html + category: security + technology: + - django + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + languages: [python] + severity: WARNING + patterns: + - pattern-inside: | + def $FUNC(...): + ... + $EMAIL.content_subtype = "html" + ... + - pattern-either: + - pattern: django.core.mail.EmailMessage($SUBJ, request.$W.get(...), ...) + - pattern: | + $DATA = request.$W.get(...) + ... + django.core.mail.EmailMessage($SUBJ, $DATA, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = $DATA + ... + django.core.mail.EmailMessage($SUBJ, $INTERM, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + django.core.mail.EmailMessage($SUBJ, $B.$C(..., $DATA, ...), ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = $B.$C(..., $DATA, ...) + ... + django.core.mail.EmailMessage($SUBJ, $INTERM, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + django.core.mail.EmailMessage($SUBJ, $STR % $DATA, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = $STR % $DATA + ... + django.core.mail.EmailMessage($SUBJ, $INTERM, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + django.core.mail.EmailMessage($SUBJ, f"...{$DATA}...", ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = f"...{$DATA}..." + ... + django.core.mail.EmailMessage($SUBJ, $INTERM, ...) + - pattern: $A = django.core.mail.EmailMessage($SUBJ, request.$W.get(...), ...) + - pattern: return django.core.mail.EmailMessage($SUBJ, request.$W.get(...), ...) + - pattern: django.core.mail.EmailMessage($SUBJ, request.$W(...), ...) + - pattern: | + $DATA = request.$W(...) + ... + django.core.mail.EmailMessage($SUBJ, $DATA, ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = $DATA + ... + django.core.mail.EmailMessage($SUBJ, $INTERM, ...) + - pattern: | + $DATA = request.$W(...) + ... + django.core.mail.EmailMessage($SUBJ, $B.$C(..., $DATA, ...), ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = $B.$C(..., $DATA, ...) + ... + django.core.mail.EmailMessage($SUBJ, $INTERM, ...) + - pattern: | + $DATA = request.$W(...) + ... + django.core.mail.EmailMessage($SUBJ, $STR % $DATA, ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = $STR % $DATA + ... + django.core.mail.EmailMessage($SUBJ, $INTERM, ...) + - pattern: | + $DATA = request.$W(...) + ... + django.core.mail.EmailMessage($SUBJ, f"...{$DATA}...", ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = f"...{$DATA}..." + ... + django.core.mail.EmailMessage($SUBJ, $INTERM, ...) + - pattern: $A = django.core.mail.EmailMessage($SUBJ, request.$W(...), ...) + - pattern: return django.core.mail.EmailMessage($SUBJ, request.$W(...), ...) + - pattern: django.core.mail.EmailMessage($SUBJ, request.$W[...], ...) + - pattern: | + $DATA = request.$W[...] + ... + django.core.mail.EmailMessage($SUBJ, $DATA, ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = $DATA + ... + django.core.mail.EmailMessage($SUBJ, $INTERM, ...) + - pattern: | + $DATA = request.$W[...] + ... + django.core.mail.EmailMessage($SUBJ, $B.$C(..., $DATA, ...), ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = $B.$C(..., $DATA, ...) + ... + django.core.mail.EmailMessage($SUBJ, $INTERM, ...) + - pattern: | + $DATA = request.$W[...] + ... + django.core.mail.EmailMessage($SUBJ, $STR % $DATA, ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = $STR % $DATA + ... + django.core.mail.EmailMessage($SUBJ, $INTERM, ...) + - pattern: | + $DATA = request.$W[...] + ... + django.core.mail.EmailMessage($SUBJ, f"...{$DATA}...", ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = f"...{$DATA}..." + ... + django.core.mail.EmailMessage($SUBJ, $INTERM, ...) + - pattern: $A = django.core.mail.EmailMessage($SUBJ, request.$W[...], ...) + - pattern: return django.core.mail.EmailMessage($SUBJ, request.$W[...], ...) + - pattern: django.core.mail.EmailMessage($SUBJ, request.$W, ...) + - pattern: | + $DATA = request.$W + ... + django.core.mail.EmailMessage($SUBJ, $DATA, ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = $DATA + ... + django.core.mail.EmailMessage($SUBJ, $INTERM, ...) + - pattern: | + $DATA = request.$W + ... + django.core.mail.EmailMessage($SUBJ, $B.$C(..., $DATA, ...), ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = $B.$C(..., $DATA, ...) + ... + django.core.mail.EmailMessage($SUBJ, $INTERM, ...) + - pattern: | + $DATA = request.$W + ... + django.core.mail.EmailMessage($SUBJ, $STR % $DATA, ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = $STR % $DATA + ... + django.core.mail.EmailMessage($SUBJ, $INTERM, ...) + - pattern: | + $DATA = request.$W + ... + django.core.mail.EmailMessage($SUBJ, f"...{$DATA}...", ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = f"...{$DATA}..." + ... + django.core.mail.EmailMessage($SUBJ, $INTERM, ...) + - pattern: $A = django.core.mail.EmailMessage($SUBJ, request.$W, ...) + - pattern: return django.core.mail.EmailMessage($SUBJ, request.$W, ...) +- id: python.django.security.injection.email.xss-send-mail-html-message.xss-send-mail-html-message + message: >- + Found request data in 'send_mail(...)' that uses 'html_message'. + This is dangerous because HTML emails are susceptible to XSS. + An attacker could inject data into this HTML email, causing XSS. + metadata: + cwe: + - "CWE-74: Improper Neutralization of Special Elements in Output Used by a Downstream Component ('Injection')" + owasp: + - A03:2021 - Injection + references: + - https://www.damonkohler.com/2008/12/email-injection.html + category: security + technology: + - django + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + languages: [python] + severity: WARNING + patterns: + - pattern-inside: | + def $FUNC(...): + ... + - pattern-either: + - pattern: django.core.mail.send_mail(..., html_message=request.$W.get(...), ...) + - pattern: | + $DATA = request.$W.get(...) + ... + django.core.mail.send_mail(..., html_message=$DATA, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = $DATA + ... + django.core.mail.send_mail(..., html_message=$INTERM, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + django.core.mail.send_mail(..., html_message=$STR.format(..., $DATA, ...), ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = $STR.format(..., $DATA, ...) + ... + django.core.mail.send_mail(..., html_message=$INTERM, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + django.core.mail.send_mail(..., html_message=$STR % $DATA, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = $STR % $DATA + ... + django.core.mail.send_mail(..., html_message=$INTERM, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + django.core.mail.send_mail(..., html_message=f"...{$DATA}...", ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = f"...{$DATA}..." + ... + django.core.mail.send_mail(..., html_message=$INTERM, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + django.core.mail.send_mail(..., html_message=$STR + $DATA, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = $STR + $DATA + ... + django.core.mail.send_mail(..., html_message=$INTERM, ...) + - pattern: $A = django.core.mail.send_mail(..., html_message=request.$W.get(...), ...) + - pattern: return django.core.mail.send_mail(..., html_message=request.$W.get(...), ...) + - pattern: django.core.mail.send_mail(..., html_message=request.$W(...), ...) + - pattern: | + $DATA = request.$W(...) + ... + django.core.mail.send_mail(..., html_message=$DATA, ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = $DATA + ... + django.core.mail.send_mail(..., html_message=$INTERM, ...) + - pattern: | + $DATA = request.$W(...) + ... + django.core.mail.send_mail(..., html_message=$STR.format(..., $DATA, ...), ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = $STR.format(..., $DATA, ...) + ... + django.core.mail.send_mail(..., html_message=$INTERM, ...) + - pattern: | + $DATA = request.$W(...) + ... + django.core.mail.send_mail(..., html_message=$STR % $DATA, ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = $STR % $DATA + ... + django.core.mail.send_mail(..., html_message=$INTERM, ...) + - pattern: | + $DATA = request.$W(...) + ... + django.core.mail.send_mail(..., html_message=f"...{$DATA}...", ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = f"...{$DATA}..." + ... + django.core.mail.send_mail(..., html_message=$INTERM, ...) + - pattern: | + $DATA = request.$W(...) + ... + django.core.mail.send_mail(..., html_message=$STR + $DATA, ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = $STR + $DATA + ... + django.core.mail.send_mail(..., html_message=$INTERM, ...) + - pattern: $A = django.core.mail.send_mail(..., html_message=request.$W(...), ...) + - pattern: return django.core.mail.send_mail(..., html_message=request.$W(...), ...) + - pattern: django.core.mail.send_mail(..., html_message=request.$W[...], ...) + - pattern: | + $DATA = request.$W[...] + ... + django.core.mail.send_mail(..., html_message=$DATA, ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = $DATA + ... + django.core.mail.send_mail(..., html_message=$INTERM, ...) + - pattern: | + $DATA = request.$W[...] + ... + django.core.mail.send_mail(..., html_message=$STR.format(..., $DATA, ...), ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = $STR.format(..., $DATA, ...) + ... + django.core.mail.send_mail(..., html_message=$INTERM, ...) + - pattern: | + $DATA = request.$W[...] + ... + django.core.mail.send_mail(..., html_message=$STR % $DATA, ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = $STR % $DATA + ... + django.core.mail.send_mail(..., html_message=$INTERM, ...) + - pattern: | + $DATA = request.$W[...] + ... + django.core.mail.send_mail(..., html_message=f"...{$DATA}...", ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = f"...{$DATA}..." + ... + django.core.mail.send_mail(..., html_message=$INTERM, ...) + - pattern: | + $DATA = request.$W[...] + ... + django.core.mail.send_mail(..., html_message=$STR + $DATA, ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = $STR + $DATA + ... + django.core.mail.send_mail(..., html_message=$INTERM, ...) + - pattern: $A = django.core.mail.send_mail(..., html_message=request.$W[...], ...) + - pattern: return django.core.mail.send_mail(..., html_message=request.$W[...], ...) + - pattern: django.core.mail.send_mail(..., html_message=request.$W, ...) + - pattern: | + $DATA = request.$W + ... + django.core.mail.send_mail(..., html_message=$DATA, ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = $DATA + ... + django.core.mail.send_mail(..., html_message=$INTERM, ...) + - pattern: | + $DATA = request.$W + ... + django.core.mail.send_mail(..., html_message=$STR.format(..., $DATA, ...), ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = $STR.format(..., $DATA, ...) + ... + django.core.mail.send_mail(..., html_message=$INTERM, ...) + - pattern: | + $DATA = request.$W + ... + django.core.mail.send_mail(..., html_message=$STR % $DATA, ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = $STR % $DATA + ... + django.core.mail.send_mail(..., html_message=$INTERM, ...) + - pattern: | + $DATA = request.$W + ... + django.core.mail.send_mail(..., html_message=f"...{$DATA}...", ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = f"...{$DATA}..." + ... + django.core.mail.send_mail(..., html_message=$INTERM, ...) + - pattern: | + $DATA = request.$W + ... + django.core.mail.send_mail(..., html_message=$STR + $DATA, ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = $STR + $DATA + ... + django.core.mail.send_mail(..., html_message=$INTERM, ...) + - pattern: $A = django.core.mail.send_mail(..., html_message=request.$W, ...) + - pattern: return django.core.mail.send_mail(..., html_message=request.$W, ...) +- id: python.django.security.injection.mass-assignment.mass-assignment + languages: [python] + severity: WARNING + message: >- + Mass assignment detected. This can result in assignment to model fields that are + unintended and can be exploited by an attacker. Instead of using '**request.$W', + assign each field you want to edit individually to prevent mass assignment. You + can read more about mass assignment at https://cheatsheetseries.owasp.org/cheatsheets/Mass_Assignment_Cheat_Sheet.html. + metadata: + cwe: + - 'CWE-915: Improperly Controlled Modification of Dynamically-Determined Object Attributes' + owasp: + - A08:2021 - Software and Data Integrity Failures + owaspapi: 'API6: Mass Assignment' + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Mass_Assignment_Cheat_Sheet.html + category: security + technology: + - django + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + pattern-either: + - pattern: $MODEL.objects.create(**request.$W) + - pattern: | + $OBJ.update(**request.$W) + ... + $OBJ.save() +- id: python.django.security.injection.open-redirect.open-redirect + message: >- + Data from request ($DATA) is passed to redirect(). This is an open redirect and could be exploited. + Ensure you are redirecting to safe URLs by using django.utils.http.is_safe_url(). + See https://cwe.mitre.org/data/definitions/601.html for more information. + metadata: + cwe: + - "CWE-601: URL Redirection to Untrusted Site ('Open Redirect')" + owasp: + - A01:2021 - Broken Access Control + references: + - https://www.djm.org.uk/posts/djangos-little-protections-word-redirect-dangers/ + - https://github.com/django/django/blob/d1b7bd030b1db111e1a3505b1fc029ab964382cc/django/utils/http.py#L231 + category: security + technology: + - django + subcategory: + - vuln + likelihood: LOW + impact: MEDIUM + confidence: MEDIUM + languages: [python] + severity: WARNING + patterns: + - pattern-inside: | + def $FUNC(...): + ... + - pattern-not-inside: | + def $FUNC(...): + ... + django.utils.http.is_safe_url(...) + ... + - pattern-not-inside: | + def $FUNC(...): + ... + if <... django.utils.http.is_safe_url(...) ...>: + ... + - pattern-not-inside: | + def $FUNC(...): + ... + django.utils.http.url_has_allowed_host_and_scheme(...) + ... + - pattern-not-inside: | + def $FUNC(...): + ... + if <... django.utils.http.url_has_allowed_host_and_scheme(...) ...>: + ... + - pattern-either: + - pattern: django.shortcuts.redirect(..., request.$W.get(...), ...) + - pattern: django.shortcuts.redirect(..., $S.format(..., request.$W.get(...), ...), ...) + - pattern: django.shortcuts.redirect(..., $S % request.$W.get(...), ...) + - pattern: django.shortcuts.redirect(..., f"...{request.$W.get(...)}...", ...) + - pattern: | + $DATA = request.$W.get(...) + ... + django.shortcuts.redirect(..., $DATA, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = $DATA + ... + django.shortcuts.redirect(..., $INTERM, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + django.shortcuts.redirect(..., $STR.format(..., $DATA, ...), ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = $STR.format(..., $DATA, ...) + ... + django.shortcuts.redirect(..., $INTERM, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + django.shortcuts.redirect(..., $STR % $DATA, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = $STR % $DATA + ... + django.shortcuts.redirect(..., $INTERM, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + django.shortcuts.redirect(..., f"...{$DATA}...", ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = f"...{$DATA}..." + ... + django.shortcuts.redirect(..., $INTERM, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + django.shortcuts.redirect(..., $STR + $DATA, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = $STR + $DATA + ... + django.shortcuts.redirect(..., $INTERM, ...) + - pattern: $A = django.shortcuts.redirect(..., request.$W.get(...), ...) + - pattern: $A = django.shortcuts.redirect(..., $S.format(..., request.$W.get(...), ...), ...) + - pattern: $A = django.shortcuts.redirect(..., $S % request.$W.get(...), ...) + - pattern: $A = django.shortcuts.redirect(..., f"...{request.$W.get(...)}...", ...) + - pattern: return django.shortcuts.redirect(..., request.$W.get(...), ...) + - pattern: return django.shortcuts.redirect(..., $S.format(..., request.$W.get(...), ...), ...) + - pattern: return django.shortcuts.redirect(..., $S % request.$W.get(...), ...) + - pattern: return django.shortcuts.redirect(..., f"...{request.$W.get(...)}...", ...) + - pattern: django.shortcuts.redirect(..., request.$W(...), ...) + - pattern: django.shortcuts.redirect(..., $S.format(..., request.$W(...), ...), ...) + - pattern: django.shortcuts.redirect(..., $S % request.$W(...), ...) + - pattern: django.shortcuts.redirect(..., f"...{request.$W(...)}...", ...) + - pattern: | + $DATA = request.$W(...) + ... + django.shortcuts.redirect(..., $DATA, ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = $DATA + ... + django.shortcuts.redirect(..., $INTERM, ...) + - pattern: | + $DATA = request.$W(...) + ... + django.shortcuts.redirect(..., $STR.format(..., $DATA, ...), ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = $STR.format(..., $DATA, ...) + ... + django.shortcuts.redirect(..., $INTERM, ...) + - pattern: | + $DATA = request.$W(...) + ... + django.shortcuts.redirect(..., $STR % $DATA, ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = $STR % $DATA + ... + django.shortcuts.redirect(..., $INTERM, ...) + - pattern: | + $DATA = request.$W(...) + ... + django.shortcuts.redirect(..., f"...{$DATA}...", ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = f"...{$DATA}..." + ... + django.shortcuts.redirect(..., $INTERM, ...) + - pattern: | + $DATA = request.$W(...) + ... + django.shortcuts.redirect(..., $STR + $DATA, ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = $STR + $DATA + ... + django.shortcuts.redirect(..., $INTERM, ...) + - pattern: $A = django.shortcuts.redirect(..., request.$W(...), ...) + - pattern: $A = django.shortcuts.redirect(..., $S.format(..., request.$W(...), ...), ...) + - pattern: $A = django.shortcuts.redirect(..., $S % request.$W(...), ...) + - pattern: $A = django.shortcuts.redirect(..., f"...{request.$W(...)}...", ...) + - pattern: return django.shortcuts.redirect(..., request.$W(...), ...) + - pattern: return django.shortcuts.redirect(..., $S.format(..., request.$W(...), ...), ...) + - pattern: return django.shortcuts.redirect(..., $S % request.$W(...), ...) + - pattern: return django.shortcuts.redirect(..., f"...{request.$W(...)}...", ...) + - pattern: django.shortcuts.redirect(..., request.$W[...], ...) + - pattern: django.shortcuts.redirect(..., $S.format(..., request.$W[...], ...), ...) + - pattern: django.shortcuts.redirect(..., $S % request.$W[...], ...) + - pattern: django.shortcuts.redirect(..., f"...{request.$W[...]}...", ...) + - pattern: | + $DATA = request.$W[...] + ... + django.shortcuts.redirect(..., $DATA, ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = $DATA + ... + django.shortcuts.redirect(..., $INTERM, ...) + - pattern: | + $DATA = request.$W[...] + ... + django.shortcuts.redirect(..., $STR.format(..., $DATA, ...), ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = $STR.format(..., $DATA, ...) + ... + django.shortcuts.redirect(..., $INTERM, ...) + - pattern: | + $DATA = request.$W[...] + ... + django.shortcuts.redirect(..., $STR % $DATA, ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = $STR % $DATA + ... + django.shortcuts.redirect(..., $INTERM, ...) + - pattern: | + $DATA = request.$W[...] + ... + django.shortcuts.redirect(..., f"...{$DATA}...", ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = f"...{$DATA}..." + ... + django.shortcuts.redirect(..., $INTERM, ...) + - pattern: | + $DATA = request.$W[...] + ... + django.shortcuts.redirect(..., $STR + $DATA, ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = $STR + $DATA + ... + django.shortcuts.redirect(..., $INTERM, ...) + - pattern: $A = django.shortcuts.redirect(..., request.$W[...], ...) + - pattern: $A = django.shortcuts.redirect(..., $S.format(..., request.$W[...], ...), ...) + - pattern: $A = django.shortcuts.redirect(..., $S % request.$W[...], ...) + - pattern: $A = django.shortcuts.redirect(..., f"...{request.$W[...]}...", ...) + - pattern: return django.shortcuts.redirect(..., request.$W[...], ...) + - pattern: return django.shortcuts.redirect(..., $S.format(..., request.$W[...], ...), ...) + - pattern: return django.shortcuts.redirect(..., $S % request.$W[...], ...) + - pattern: return django.shortcuts.redirect(..., f"...{request.$W[...]}...", ...) + - pattern: django.shortcuts.redirect(..., request.$W, ...) + - pattern: django.shortcuts.redirect(..., $S.format(..., request.$W, ...), ...) + - pattern: django.shortcuts.redirect(..., $S % request.$W, ...) + - pattern: django.shortcuts.redirect(..., f"...{request.$W}...", ...) + - pattern: | + $DATA = request.$W + ... + django.shortcuts.redirect(..., $DATA, ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = $DATA + ... + django.shortcuts.redirect(..., $INTERM, ...) + - pattern: | + $DATA = request.$W + ... + django.shortcuts.redirect(..., $STR.format(..., $DATA, ...), ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = $STR.format(..., $DATA, ...) + ... + django.shortcuts.redirect(..., $INTERM, ...) + - pattern: | + $DATA = request.$W + ... + django.shortcuts.redirect(..., $STR % $DATA, ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = $STR % $DATA + ... + django.shortcuts.redirect(..., $INTERM, ...) + - pattern: | + $DATA = request.$W + ... + django.shortcuts.redirect(..., f"...{$DATA}...", ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = f"...{$DATA}..." + ... + django.shortcuts.redirect(..., $INTERM, ...) + - pattern: | + $DATA = request.$W + ... + django.shortcuts.redirect(..., $STR + $DATA, ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = $STR + $DATA + ... + django.shortcuts.redirect(..., $INTERM, ...) + - pattern: $A = django.shortcuts.redirect(..., request.$W, ...) + - pattern: $A = django.shortcuts.redirect(..., $S.format(..., request.$W, ...), ...) + - pattern: $A = django.shortcuts.redirect(..., $S % request.$W, ...) + - pattern: $A = django.shortcuts.redirect(..., f"...{request.$W}...", ...) + - pattern: return django.shortcuts.redirect(..., request.$W, ...) + - pattern: return django.shortcuts.redirect(..., $S.format(..., request.$W, ...), ...) + - pattern: return django.shortcuts.redirect(..., $S % request.$W, ...) + - pattern: return django.shortcuts.redirect(..., f"...{request.$W}...", ...) + - pattern: django.http.HttpResponseRedirect(..., request.$W.get(...), ...) + - pattern: django.http.HttpResponseRedirect(..., $S.format(..., request.$W.get(...), ...), ...) + - pattern: django.http.HttpResponseRedirect(..., $S % request.$W.get(...), ...) + - pattern: django.http.HttpResponseRedirect(..., f"...{request.$W.get(...)}...", ...) + - pattern: | + $DATA = request.$W.get(...) + ... + django.http.HttpResponseRedirect(..., $DATA, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = $DATA + ... + django.http.HttpResponseRedirect(..., $INTERM, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + django.http.HttpResponseRedirect(..., $STR.format(..., $DATA, ...), ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = $STR.format(..., $DATA, ...) + ... + django.http.HttpResponseRedirect(..., $INTERM, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + django.http.HttpResponseRedirect(..., $STR % $DATA, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = $STR % $DATA + ... + django.http.HttpResponseRedirect(..., $INTERM, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + django.http.HttpResponseRedirect(..., f"...{$DATA}...", ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = f"...{$DATA}..." + ... + django.http.HttpResponseRedirect(..., $INTERM, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + django.http.HttpResponseRedirect(..., $STR + $DATA, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = $STR + $DATA + ... + django.http.HttpResponseRedirect(..., $INTERM, ...) + - pattern: $A = django.http.HttpResponseRedirect(..., request.$W.get(...), ...) + - pattern: $A = django.http.HttpResponseRedirect(..., $S.format(..., request.$W.get(...), ...), ...) + - pattern: $A = django.http.HttpResponseRedirect(..., $S % request.$W.get(...), ...) + - pattern: $A = django.http.HttpResponseRedirect(..., f"...{request.$W.get(...)}...", ...) + - pattern: return django.http.HttpResponseRedirect(..., request.$W.get(...), ...) + - pattern: return django.http.HttpResponseRedirect(..., $S.format(..., request.$W.get(...), ...), + ...) + - pattern: return django.http.HttpResponseRedirect(..., $S % request.$W.get(...), ...) + - pattern: return django.http.HttpResponseRedirect(..., f"...{request.$W.get(...)}...", ...) + - pattern: django.http.HttpResponseRedirect(..., request.$W(...), ...) + - pattern: django.http.HttpResponseRedirect(..., $S.format(..., request.$W(...), ...), ...) + - pattern: django.http.HttpResponseRedirect(..., $S % request.$W(...), ...) + - pattern: django.http.HttpResponseRedirect(..., f"...{request.$W(...)}...", ...) + - pattern: | + $DATA = request.$W(...) + ... + django.http.HttpResponseRedirect(..., $DATA, ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = $DATA + ... + django.http.HttpResponseRedirect(..., $INTERM, ...) + - pattern: | + $DATA = request.$W(...) + ... + django.http.HttpResponseRedirect(..., $STR.format(..., $DATA, ...), ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = $STR.format(..., $DATA, ...) + ... + django.http.HttpResponseRedirect(..., $INTERM, ...) + - pattern: | + $DATA = request.$W(...) + ... + django.http.HttpResponseRedirect(..., $STR % $DATA, ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = $STR % $DATA + ... + django.http.HttpResponseRedirect(..., $INTERM, ...) + - pattern: | + $DATA = request.$W(...) + ... + django.http.HttpResponseRedirect(..., f"...{$DATA}...", ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = f"...{$DATA}..." + ... + django.http.HttpResponseRedirect(..., $INTERM, ...) + - pattern: | + $DATA = request.$W(...) + ... + django.http.HttpResponseRedirect(..., $STR + $DATA, ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = $STR + $DATA + ... + django.http.HttpResponseRedirect(..., $INTERM, ...) + - pattern: $A = django.http.HttpResponseRedirect(..., request.$W(...), ...) + - pattern: $A = django.http.HttpResponseRedirect(..., $S.format(..., request.$W(...), ...), ...) + - pattern: $A = django.http.HttpResponseRedirect(..., $S % request.$W(...), ...) + - pattern: $A = django.http.HttpResponseRedirect(..., f"...{request.$W(...)}...", ...) + - pattern: return django.http.HttpResponseRedirect(..., request.$W(...), ...) + - pattern: return django.http.HttpResponseRedirect(..., $S.format(..., request.$W(...), ...), ...) + - pattern: return django.http.HttpResponseRedirect(..., $S % request.$W(...), ...) + - pattern: return django.http.HttpResponseRedirect(..., f"...{request.$W(...)}...", ...) + - pattern: django.http.HttpResponseRedirect(..., request.$W[...], ...) + - pattern: django.http.HttpResponseRedirect(..., $S.format(..., request.$W[...], ...), ...) + - pattern: django.http.HttpResponseRedirect(..., $S % request.$W[...], ...) + - pattern: django.http.HttpResponseRedirect(..., f"...{request.$W[...]}...", ...) + - pattern: | + $DATA = request.$W[...] + ... + django.http.HttpResponseRedirect(..., $DATA, ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = $DATA + ... + django.http.HttpResponseRedirect(..., $INTERM, ...) + - pattern: | + $DATA = request.$W[...] + ... + django.http.HttpResponseRedirect(..., $STR.format(..., $DATA, ...), ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = $STR.format(..., $DATA, ...) + ... + django.http.HttpResponseRedirect(..., $INTERM, ...) + - pattern: | + $DATA = request.$W[...] + ... + django.http.HttpResponseRedirect(..., $STR % $DATA, ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = $STR % $DATA + ... + django.http.HttpResponseRedirect(..., $INTERM, ...) + - pattern: | + $DATA = request.$W[...] + ... + django.http.HttpResponseRedirect(..., f"...{$DATA}...", ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = f"...{$DATA}..." + ... + django.http.HttpResponseRedirect(..., $INTERM, ...) + - pattern: | + $DATA = request.$W[...] + ... + django.http.HttpResponseRedirect(..., $STR + $DATA, ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = $STR + $DATA + ... + django.http.HttpResponseRedirect(..., $INTERM, ...) + - pattern: $A = django.http.HttpResponseRedirect(..., request.$W[...], ...) + - pattern: $A = django.http.HttpResponseRedirect(..., $S.format(..., request.$W[...], ...), ...) + - pattern: $A = django.http.HttpResponseRedirect(..., $S % request.$W[...], ...) + - pattern: $A = django.http.HttpResponseRedirect(..., f"...{request.$W[...]}...", ...) + - pattern: return django.http.HttpResponseRedirect(..., request.$W[...], ...) + - pattern: return django.http.HttpResponseRedirect(..., $S.format(..., request.$W[...], ...), ...) + - pattern: return django.http.HttpResponseRedirect(..., $S % request.$W[...], ...) + - pattern: return django.http.HttpResponseRedirect(..., f"...{request.$W[...]}...", ...) + - pattern: django.http.HttpResponseRedirect(..., request.$W, ...) + - pattern: django.http.HttpResponseRedirect(..., $S.format(..., request.$W, ...), ...) + - pattern: django.http.HttpResponseRedirect(..., $S % request.$W, ...) + - pattern: django.http.HttpResponseRedirect(..., f"...{request.$W}...", ...) + - pattern: | + $DATA = request.$W + ... + django.http.HttpResponseRedirect(..., $DATA, ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = $DATA + ... + django.http.HttpResponseRedirect(..., $INTERM, ...) + - pattern: | + $DATA = request.$W + ... + django.http.HttpResponseRedirect(..., $STR.format(..., $DATA, ...), ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = $STR.format(..., $DATA, ...) + ... + django.http.HttpResponseRedirect(..., $INTERM, ...) + - pattern: | + $DATA = request.$W + ... + django.http.HttpResponseRedirect(..., $STR % $DATA, ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = $STR % $DATA + ... + django.http.HttpResponseRedirect(..., $INTERM, ...) + - pattern: | + $DATA = request.$W + ... + django.http.HttpResponseRedirect(..., f"...{$DATA}...", ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = f"...{$DATA}..." + ... + django.http.HttpResponseRedirect(..., $INTERM, ...) + - pattern: | + $DATA = request.$W + ... + django.http.HttpResponseRedirect(..., $STR + $DATA, ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = $STR + $DATA + ... + django.http.HttpResponseRedirect(..., $INTERM, ...) + - pattern: $A = django.http.HttpResponseRedirect(..., request.$W, ...) + - pattern: $A = django.http.HttpResponseRedirect(..., $S.format(..., request.$W, ...), ...) + - pattern: $A = django.http.HttpResponseRedirect(..., $S % request.$W, ...) + - pattern: $A = django.http.HttpResponseRedirect(..., f"...{request.$W}...", ...) + - pattern: return django.http.HttpResponseRedirect(..., request.$W, ...) + - pattern: return django.http.HttpResponseRedirect(..., $S.format(..., request.$W, ...), ...) + - pattern: return django.http.HttpResponseRedirect(..., $S % request.$W, ...) + - pattern: return django.http.HttpResponseRedirect(..., f"...{request.$W}...", ...) + - metavariable-regex: + metavariable: $W + regex: (?!get_full_path) +- id: python.django.security.injection.path-traversal.path-traversal-file-name.path-traversal-file-name + message: >- + Data from request is passed to a file name `$FILE`. This is a path traversal vulnerability, which + can lead to sensitive data being leaked. To mitigate, consider using os.path.abspath or os.path.realpath + or the pathlib library. + metadata: + cwe: + - "CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')" + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + references: + - https://owasp.org/www-community/attacks/Path_Traversal + category: security + technology: + - django + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: LOW + impact: MEDIUM + confidence: LOW + patterns: + - pattern-inside: | + def $F(...): + ... + - pattern-not-inside: | + def $F(...): + ... + os.path.realpath(...) + ... + - pattern-not-inside: | + def $F(...): + ... + os.path.abspath(...) + ... + - pattern-either: + # match % use cases + - pattern: | + $V = request.$W.get($X) + ... + $FILE % ($V) + - pattern: | + $V = request.$W[$X] + ... + $FILE % ($V) + - pattern: | + $V = request.$W($X) + ... + $FILE % ($V) + - pattern: | + $V = request.$W + ... + $FILE % ($V) + # match format use cases + - pattern: | + $V = request.$W.get($X) + ... + $FILE.format(..., $V, ...) + - pattern: | + $V = request.$W[$X] + ... + $FILE.format(..., $V, ...) + - pattern: | + $V = request.$W($X) + ... + $FILE.format(..., $V, ...) + - pattern: | + $V = request.$W + ... + $FILE.format(..., $V, ...) + - metavariable-regex: + metavariable: $FILE + regex: .*\.(log|zip|txt|csv|xml|html).* + languages: [python] + severity: WARNING +- id: python.django.security.injection.path-traversal.path-traversal-join.path-traversal-join + message: >- + Data from request is passed to os.path.join() and to open(). This is a path traversal vulnerability, + which can lead to sensitive data being leaked. To mitigate, consider using os.path.abspath or os.path.realpath + or Path library. + metadata: + cwe: + - "CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')" + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + references: + - https://owasp.org/www-community/attacks/Path_Traversal + category: security + technology: + - django + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + patterns: + - pattern-inside: | + def $F(...): + ... + - pattern-not-inside: | + def $F(...): + ... + os.path.abspath(...) + ... + - pattern-not-inside: | + def $F(...): + ... + os.path.realpath(...) + ... + - pattern-either: + - pattern: open(os.path.join(..., request.$W.get(...), ...), ...) + - pattern: open(os.path.join(..., request.$W(...), ...), ...) + - pattern: open(os.path.join(..., request.$W, ...), ...) + - pattern: open(os.path.join(..., request.$W[...], ...), ...) + - pattern: | + $P = os.path.join(..., request.$W.get(...), ...) + ... + open($P, ...) + - pattern: | + $P = os.path.join(..., request.$W(...), ...) + ... + open($P, ...) + - pattern: | + $P = os.path.join(..., request.$W, ...) + ... + open($P, ...) + - pattern: | + $P = os.path.join(..., request.$W[...], ...) + ... + open($P, ...) + - pattern: | + $V = request.$W.get($X) + ... + $P = os.path.join(..., $V, ...) + ... + open($P, ...) + - pattern: | + $V = request.$W($X) + ... + $P = os.path.join(..., $V, ...) + ... + open($P, ...) + - pattern: | + $V = request.$W[$X] + ... + $P = os.path.join(..., $V, ...) + ... + open($P, ...) + - pattern: | + $V = request.$W + ... + $P = os.path.join(..., $V, ...) + ... + open($P, ...) + - pattern: | + $P = request.$W.get(...) + ... + open(os.path.join(..., $P, ...), ...) + - pattern: | + $P = request.$W(...) + ... + open(os.path.join(..., $P, ...), ...) + - pattern: | + $P = request.$W + ... + open(os.path.join(..., $P, ...), ...) + - pattern: | + $P = request.$W[...] + ... + open(os.path.join(..., $P, ...), ...) + languages: [python] + severity: WARNING +- id: python.django.security.injection.path-traversal.path-traversal-open.path-traversal-open + message: >- + Found request data in a call to 'open'. Ensure the request data is validated or sanitized, otherwise + it could result in path traversal attacks and therefore sensitive data being leaked. + To mitigate, consider using os.path.abspath or os.path.realpath + or the pathlib library. + metadata: + cwe: + - "CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')" + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + references: + - https://owasp.org/www-community/attacks/Path_Traversal + category: security + technology: + - django + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + languages: [python] + severity: WARNING + patterns: + - pattern-inside: | + def $FUNC(...): + ... + - pattern-either: + - pattern: open(..., request.$W.get(...), ...) + - pattern: open(..., $S.format(..., request.$W.get(...), ...), ...) + - pattern: open(..., $S % request.$W.get(...), ...) + - pattern: open(..., f"...{request.$W.get(...)}...", ...) + - pattern: | + $DATA = request.$W.get(...) + ... + open(..., $DATA, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = $DATA + ... + open(..., $INTERM, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = $DATA + ... + with open(..., $INTERM, ...) as $FD: + ... + - pattern: | + $DATA = request.$W.get(...) + ... + open(..., $STR.format(..., $DATA, ...), ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = $STR.format(..., $DATA, ...) + ... + open(..., $INTERM, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = $STR.format(..., $DATA, ...) + ... + with open(..., $INTERM, ...) as $FD: + ... + - pattern: | + $DATA = request.$W.get(...) + ... + open(..., $STR % $DATA, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = $STR % $DATA + ... + open(..., $INTERM, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = $STR % $DATA + ... + with open(..., $INTERM, ...) as $FD: + ... + - pattern: | + $DATA = request.$W.get(...) + ... + open(..., f"...{$DATA}...", ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = f"...{$DATA}..." + ... + open(..., $INTERM, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = f"...{$DATA}..." + ... + with open(..., $INTERM, ...) as $FD: + ... + - pattern: | + $DATA = request.$W.get(...) + ... + open(..., $STR + $DATA, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = $STR + $DATA + ... + open(..., $INTERM, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = $STR + $DATA + ... + with open(..., $INTERM, ...) as $FD: + ... + - pattern: $A = open(..., request.$W.get(...), ...) + - pattern: $A = open(..., $S.format(..., request.$W.get(...), ...), ...) + - pattern: $A = open(..., $S % request.$W.get(...), ...) + - pattern: $A = open(..., f"...{request.$W.get(...)}...", ...) + - pattern: return open(..., request.$W.get(...), ...) + - pattern: return open(..., $S.format(..., request.$W.get(...), ...), ...) + - pattern: return open(..., $S % request.$W.get(...), ...) + - pattern: return open(..., f"...{request.$W.get(...)}...", ...) + - pattern: | + $DATA = request.$W.get(...) + ... + with open(..., $DATA, ...) as $FD: + ... + - pattern: open(..., request.$W(...), ...) + - pattern: open(..., $S.format(..., request.$W(...), ...), ...) + - pattern: open(..., $S % request.$W(...), ...) + - pattern: open(..., f"...{request.$W(...)}...", ...) + - pattern: | + $DATA = request.$W(...) + ... + open(..., $DATA, ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = $DATA + ... + open(..., $INTERM, ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = $DATA + ... + with open(..., $INTERM, ...) as $FD: + ... + - pattern: | + $DATA = request.$W(...) + ... + open(..., $STR.format(..., $DATA, ...), ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = $STR.format(..., $DATA, ...) + ... + open(..., $INTERM, ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = $STR.format(..., $DATA, ...) + ... + with open(..., $INTERM, ...) as $FD: + ... + - pattern: | + $DATA = request.$W(...) + ... + open(..., $STR % $DATA, ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = $STR % $DATA + ... + open(..., $INTERM, ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = $STR % $DATA + ... + with open(..., $INTERM, ...) as $FD: + ... + - pattern: | + $DATA = request.$W(...) + ... + open(..., f"...{$DATA}...", ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = f"...{$DATA}..." + ... + open(..., $INTERM, ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = f"...{$DATA}..." + ... + with open(..., $INTERM, ...) as $FD: + ... + - pattern: | + $DATA = request.$W(...) + ... + open(..., $STR + $DATA, ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = $STR + $DATA + ... + open(..., $INTERM, ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = $STR + $DATA + ... + with open(..., $INTERM, ...) as $FD: + ... + - pattern: $A = open(..., request.$W(...), ...) + - pattern: $A = open(..., $S.format(..., request.$W(...), ...), ...) + - pattern: $A = open(..., $S % request.$W(...), ...) + - pattern: $A = open(..., f"...{request.$W(...)}...", ...) + - pattern: return open(..., request.$W(...), ...) + - pattern: return open(..., $S.format(..., request.$W(...), ...), ...) + - pattern: return open(..., $S % request.$W(...), ...) + - pattern: return open(..., f"...{request.$W(...)}...", ...) + - pattern: | + $DATA = request.$W(...) + ... + with open(..., $DATA, ...) as $FD: + ... + - pattern: open(..., request.$W[...], ...) + - pattern: open(..., $S.format(..., request.$W[...], ...), ...) + - pattern: open(..., $S % request.$W[...], ...) + - pattern: open(..., f"...{request.$W[...]}...", ...) + - pattern: | + $DATA = request.$W[...] + ... + open(..., $DATA, ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = $DATA + ... + open(..., $INTERM, ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = $DATA + ... + with open(..., $INTERM, ...) as $FD: + ... + - pattern: | + $DATA = request.$W[...] + ... + open(..., $STR.format(..., $DATA, ...), ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = $STR.format(..., $DATA, ...) + ... + open(..., $INTERM, ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = $STR.format(..., $DATA, ...) + ... + with open(..., $INTERM, ...) as $FD: + ... + - pattern: | + $DATA = request.$W[...] + ... + open(..., $STR % $DATA, ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = $STR % $DATA + ... + open(..., $INTERM, ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = $STR % $DATA + ... + with open(..., $INTERM, ...) as $FD: + ... + - pattern: | + $DATA = request.$W[...] + ... + open(..., f"...{$DATA}...", ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = f"...{$DATA}..." + ... + open(..., $INTERM, ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = f"...{$DATA}..." + ... + with open(..., $INTERM, ...) as $FD: + ... + - pattern: | + $DATA = request.$W[...] + ... + open(..., $STR + $DATA, ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = $STR + $DATA + ... + open(..., $INTERM, ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = $STR + $DATA + ... + with open(..., $INTERM, ...) as $FD: + ... + - pattern: $A = open(..., request.$W[...], ...) + - pattern: $A = open(..., $S.format(..., request.$W[...], ...), ...) + - pattern: $A = open(..., $S % request.$W[...], ...) + - pattern: $A = open(..., f"...{request.$W[...]}...", ...) + - pattern: return open(..., request.$W[...], ...) + - pattern: return open(..., $S.format(..., request.$W[...], ...), ...) + - pattern: return open(..., $S % request.$W[...], ...) + - pattern: return open(..., f"...{request.$W[...]}...", ...) + - pattern: | + $DATA = request.$W[...] + ... + with open(..., $DATA, ...) as $FD: + ... + - pattern: open(..., request.$W, ...) + - pattern: open(..., $S.format(..., request.$W, ...), ...) + - pattern: open(..., $S % request.$W, ...) + - pattern: open(..., f"...{request.$W}...", ...) + - pattern: | + $DATA = request.$W + ... + open(..., $DATA, ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = $DATA + ... + open(..., $INTERM, ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = $DATA + ... + with open(..., $INTERM, ...) as $FD: + ... + - pattern: | + $DATA = request.$W + ... + open(..., $STR.format(..., $DATA, ...), ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = $STR.format(..., $DATA, ...) + ... + open(..., $INTERM, ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = $STR.format(..., $DATA, ...) + ... + with open(..., $INTERM, ...) as $FD: + ... + - pattern: | + $DATA = request.$W + ... + open(..., $STR % $DATA, ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = $STR % $DATA + ... + open(..., $INTERM, ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = $STR % $DATA + ... + with open(..., $INTERM, ...) as $FD: + ... + - pattern: | + $DATA = request.$W + ... + open(..., f"...{$DATA}...", ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = f"...{$DATA}..." + ... + open(..., $INTERM, ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = f"...{$DATA}..." + ... + with open(..., $INTERM, ...) as $FD: + ... + - pattern: | + $DATA = request.$W + ... + open(..., $STR + $DATA, ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = $STR + $DATA + ... + open(..., $INTERM, ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = $STR + $DATA + ... + with open(..., $INTERM, ...) as $FD: + ... + - pattern: $A = open(..., request.$W, ...) + - pattern: $A = open(..., $S.format(..., request.$W, ...), ...) + - pattern: $A = open(..., $S % request.$W, ...) + - pattern: $A = open(..., f"...{request.$W}...", ...) + - pattern: return open(..., request.$W, ...) + - pattern: return open(..., $S.format(..., request.$W, ...), ...) + - pattern: return open(..., $S % request.$W, ...) + - pattern: return open(..., f"...{request.$W}...", ...) + - pattern: | + $DATA = request.$W + ... + with open(..., $DATA, ...) as $FD: + ... +- id: python.django.security.injection.raw-html-format.raw-html-format + languages: + - python + severity: WARNING + message: Detected user input flowing into a manually constructed HTML string. You may be accidentally + bypassing secure methods of rendering HTML by manually constructing HTML and this could create a cross-site + scripting vulnerability, which could let attackers steal sensitive user data. To be sure this is safe, + check that the HTML is rendered safely. Otherwise, use templates (`django.shortcuts.render`) which + will safely render HTML instead. + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + category: security + technology: + - django + references: + - https://docs.djangoproject.com/en/3.2/topics/http/shortcuts/#render + - https://docs.djangoproject.com/en/3.2/topics/security/#cross-site-scripting-xss-protection + license: Commons Clause License Condition v1.0[LGPL-2.1-only] + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: HIGH + impact: MEDIUM + confidence: MEDIUM + mode: taint + pattern-sanitizers: + - pattern: django.utils.html.escape(...) + pattern-sources: + - patterns: + - pattern: request.$ANYTHING + - pattern-not: request.build_absolute_uri + pattern-sinks: + - patterns: + - pattern-either: + - patterns: + - pattern-either: + - pattern: '"$HTMLSTR" % ...' + - pattern: '"$HTMLSTR".format(...)' + - pattern: '"$HTMLSTR" + ...' + - pattern: f"$HTMLSTR{...}..." + - patterns: + - pattern-inside: | + $HTML = "$HTMLSTR" + ... + - pattern-either: + - pattern: $HTML % ... + - pattern: $HTML.format(...) + - pattern: $HTML + ... + - metavariable-pattern: + metavariable: $HTMLSTR + language: generic + pattern: <$TAG ... +- id: python.django.security.injection.reflected-data-httpresponse.reflected-data-httpresponse + message: Found user-controlled request data passed into HttpResponse. This could be vulnerable to XSS, + leading to attackers gaining access to user cookies and protected information. Ensure that the request + data is properly escaped or sanitzed. + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + references: + - https://django-book.readthedocs.io/en/latest/chapter20.html#cross-site-scripting-xss + category: security + technology: + - django + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + languages: [python] + severity: WARNING + patterns: + - pattern-inside: | + def $FUNC(...): + ... + - pattern-either: + - pattern: django.http.HttpResponse(..., $S.format(..., request.$W.get(...), ...), ...) + - pattern: django.http.HttpResponse(..., $S % request.$W.get(...), ...) + - pattern: django.http.HttpResponse(..., f"...{request.$W.get(...)}...", ...) + - pattern: django.http.HttpResponse(..., request.$W.get(...), ...) + - pattern: | + $DATA = request.$W.get(...) + ... + django.http.HttpResponse(..., $DATA, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = $DATA + ... + django.http.HttpResponse(..., $INTERM, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + django.http.HttpResponse(..., $STR.format(..., $DATA, ...), ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = $STR.format(..., $DATA, ...) + ... + django.http.HttpResponse(..., $INTERM, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + django.http.HttpResponse(..., $STR % $DATA, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = $STR % $DATA + ... + django.http.HttpResponse(..., $INTERM, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + django.http.HttpResponse(..., f"...{$DATA}...", ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = f"...{$DATA}..." + ... + django.http.HttpResponse(..., $INTERM, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + django.http.HttpResponse(..., $STR + $DATA, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = $STR + $DATA + ... + django.http.HttpResponse(..., $INTERM, ...) + - pattern: $A = django.http.HttpResponse(..., request.$W.get(...), ...) + - pattern: return django.http.HttpResponse(..., request.$W.get(...), ...) + - pattern: django.http.HttpResponse(..., $S.format(..., request.$W(...), ...), ...) + - pattern: django.http.HttpResponse(..., $S % request.$W(...), ...) + - pattern: django.http.HttpResponse(..., f"...{request.$W(...)}...", ...) + - pattern: django.http.HttpResponse(..., request.$W(...), ...) + - pattern: | + $DATA = request.$W(...) + ... + django.http.HttpResponse(..., $DATA, ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = $DATA + ... + django.http.HttpResponse(..., $INTERM, ...) + - pattern: | + $DATA = request.$W(...) + ... + django.http.HttpResponse(..., $STR.format(..., $DATA, ...), ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = $STR.format(..., $DATA, ...) + ... + django.http.HttpResponse(..., $INTERM, ...) + - pattern: | + $DATA = request.$W(...) + ... + django.http.HttpResponse(..., $STR % $DATA, ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = $STR % $DATA + ... + django.http.HttpResponse(..., $INTERM, ...) + - pattern: | + $DATA = request.$W(...) + ... + django.http.HttpResponse(..., f"...{$DATA}...", ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = f"...{$DATA}..." + ... + django.http.HttpResponse(..., $INTERM, ...) + - pattern: | + $DATA = request.$W(...) + ... + django.http.HttpResponse(..., $STR + $DATA, ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = $STR + $DATA + ... + django.http.HttpResponse(..., $INTERM, ...) + - pattern: $A = django.http.HttpResponse(..., request.$W(...), ...) + - pattern: return django.http.HttpResponse(..., request.$W(...), ...) + - pattern: django.http.HttpResponse(..., $S.format(..., request.$W[...], ...), ...) + - pattern: django.http.HttpResponse(..., $S % request.$W[...], ...) + - pattern: django.http.HttpResponse(..., f"...{request.$W[...]}...", ...) + - pattern: django.http.HttpResponse(..., request.$W[...], ...) + - pattern: | + $DATA = request.$W[...] + ... + django.http.HttpResponse(..., $DATA, ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = $DATA + ... + django.http.HttpResponse(..., $INTERM, ...) + - pattern: | + $DATA = request.$W[...] + ... + django.http.HttpResponse(..., $STR.format(..., $DATA, ...), ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = $STR.format(..., $DATA, ...) + ... + django.http.HttpResponse(..., $INTERM, ...) + - pattern: | + $DATA = request.$W[...] + ... + django.http.HttpResponse(..., $STR % $DATA, ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = $STR % $DATA + ... + django.http.HttpResponse(..., $INTERM, ...) + - pattern: | + $DATA = request.$W[...] + ... + django.http.HttpResponse(..., f"...{$DATA}...", ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = f"...{$DATA}..." + ... + django.http.HttpResponse(..., $INTERM, ...) + - pattern: | + $DATA = request.$W[...] + ... + django.http.HttpResponse(..., $STR + $DATA, ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = $STR + $DATA + ... + django.http.HttpResponse(..., $INTERM, ...) + - pattern: $A = django.http.HttpResponse(..., request.$W[...], ...) + - pattern: return django.http.HttpResponse(..., request.$W[...], ...) + - pattern: django.http.HttpResponse(..., $S.format(..., request.$W, ...), ...) + - pattern: django.http.HttpResponse(..., $S % request.$W, ...) + - pattern: django.http.HttpResponse(..., f"...{request.$W}...", ...) + - pattern: django.http.HttpResponse(..., request.$W, ...) + - pattern: | + $DATA = request.$W + ... + django.http.HttpResponse(..., $DATA, ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = $DATA + ... + django.http.HttpResponse(..., $INTERM, ...) + - pattern: | + $DATA = request.$W + ... + django.http.HttpResponse(..., $STR.format(..., $DATA, ...), ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = $STR.format(..., $DATA, ...) + ... + django.http.HttpResponse(..., $INTERM, ...) + - pattern: | + $DATA = request.$W + ... + django.http.HttpResponse(..., $STR % $DATA, ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = $STR % $DATA + ... + django.http.HttpResponse(..., $INTERM, ...) + - pattern: | + $DATA = request.$W + ... + django.http.HttpResponse(..., f"...{$DATA}...", ...) + - pattern: $A = django.http.HttpResponse(..., request.$W, ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = $STR + $DATA + ... + $A = django.http.HttpResponse(..., $INTERM, ...) + - pattern: return django.http.HttpResponse(..., request.$W, ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = f"...{$DATA}..." + ... + django.http.HttpResponse(..., $INTERM, ...) + - pattern: | + $DATA = request.$W + ... + django.http.HttpResponse(..., $STR + $DATA, ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = $STR + $DATA + ... + django.http.HttpResponse(..., $INTERM, ...) +- id: python.django.security.injection.reflected-data-httpresponsebadrequest.reflected-data-httpresponsebadrequest + message: Found user-controlled request data passed into a HttpResponseBadRequest. This could be vulnerable + to XSS, leading to attackers gaining access to user cookies and protected information. Ensure that + the request data is properly escaped or sanitzed. + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + references: + - https://django-book.readthedocs.io/en/latest/chapter20.html#cross-site-scripting-xss + category: security + technology: + - django + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: LOW + impact: MEDIUM + confidence: MEDIUM + languages: [python] + severity: WARNING + patterns: + - pattern-inside: | + def $FUNC(...): + ... + - pattern-either: + - pattern: django.http.HttpResponseBadRequest(..., $S.format(..., request.$W.get(...), ...), ...) + - pattern: django.http.HttpResponseBadRequest(..., $S % request.$W.get(...), ...) + - pattern: django.http.HttpResponseBadRequest(..., f"...{request.$W.get(...)}...", ...) + - pattern: django.http.HttpResponseBadRequest(..., request.$W.get(...), ...) + - pattern: | + $DATA = request.$W.get(...) + ... + django.http.HttpResponseBadRequest(..., $DATA, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = $DATA + ... + django.http.HttpResponseBadRequest(..., $INTERM, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + django.http.HttpResponseBadRequest(..., $STR.format(..., $DATA, ...), ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = $STR.format(..., $DATA, ...) + ... + django.http.HttpResponseBadRequest(..., $INTERM, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + django.http.HttpResponseBadRequest(..., $STR % $DATA, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = $STR % $DATA + ... + django.http.HttpResponseBadRequest(..., $INTERM, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + django.http.HttpResponseBadRequest(..., f"...{$DATA}...", ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = f"...{$DATA}..." + ... + django.http.HttpResponseBadRequest(..., $INTERM, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + django.http.HttpResponseBadRequest(..., $STR + $DATA, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = $STR + $DATA + ... + django.http.HttpResponseBadRequest(..., $INTERM, ...) + - pattern: $A = django.http.HttpResponseBadRequest(..., request.$W.get(...), ...) + - pattern: return django.http.HttpResponseBadRequest(..., request.$W.get(...), ...) + - pattern: django.http.HttpResponseBadRequest(..., $S.format(..., request.$W(...), ...), ...) + - pattern: django.http.HttpResponseBadRequest(..., $S % request.$W(...), ...) + - pattern: django.http.HttpResponseBadRequest(..., f"...{request.$W(...)}...", ...) + - pattern: django.http.HttpResponseBadRequest(..., request.$W(...), ...) + - pattern: | + $DATA = request.$W(...) + ... + django.http.HttpResponseBadRequest(..., $DATA, ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = $DATA + ... + django.http.HttpResponseBadRequest(..., $INTERM, ...) + - pattern: | + $DATA = request.$W(...) + ... + django.http.HttpResponseBadRequest(..., $STR.format(..., $DATA, ...), ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = $STR.format(..., $DATA, ...) + ... + django.http.HttpResponseBadRequest(..., $INTERM, ...) + - pattern: | + $DATA = request.$W(...) + ... + django.http.HttpResponseBadRequest(..., $STR % $DATA, ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = $STR % $DATA + ... + django.http.HttpResponseBadRequest(..., $INTERM, ...) + - pattern: | + $DATA = request.$W(...) + ... + django.http.HttpResponseBadRequest(..., f"...{$DATA}...", ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = f"...{$DATA}..." + ... + django.http.HttpResponseBadRequest(..., $INTERM, ...) + - pattern: | + $DATA = request.$W(...) + ... + django.http.HttpResponseBadRequest(..., $STR + $DATA, ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = $STR + $DATA + ... + django.http.HttpResponseBadRequest(..., $INTERM, ...) + - pattern: $A = django.http.HttpResponseBadRequest(..., request.$W(...), ...) + - pattern: return django.http.HttpResponseBadRequest(..., request.$W(...), ...) + - pattern: django.http.HttpResponseBadRequest(..., $S.format(..., request.$W[...], ...), ...) + - pattern: django.http.HttpResponseBadRequest(..., $S % request.$W[...], ...) + - pattern: django.http.HttpResponseBadRequest(..., f"...{request.$W[...]}...", ...) + - pattern: django.http.HttpResponseBadRequest(..., request.$W[...], ...) + - pattern: | + $DATA = request.$W[...] + ... + django.http.HttpResponseBadRequest(..., $DATA, ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = $DATA + ... + django.http.HttpResponseBadRequest(..., $INTERM, ...) + - pattern: | + $DATA = request.$W[...] + ... + django.http.HttpResponseBadRequest(..., $STR.format(..., $DATA, ...), ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = $STR.format(..., $DATA, ...) + ... + django.http.HttpResponseBadRequest(..., $INTERM, ...) + - pattern: | + $DATA = request.$W[...] + ... + django.http.HttpResponseBadRequest(..., $STR % $DATA, ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = $STR % $DATA + ... + django.http.HttpResponseBadRequest(..., $INTERM, ...) + - pattern: | + $DATA = request.$W[...] + ... + django.http.HttpResponseBadRequest(..., f"...{$DATA}...", ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = f"...{$DATA}..." + ... + django.http.HttpResponseBadRequest(..., $INTERM, ...) + - pattern: | + $DATA = request.$W[...] + ... + django.http.HttpResponseBadRequest(..., $STR + $DATA, ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = $STR + $DATA + ... + django.http.HttpResponseBadRequest(..., $INTERM, ...) + - pattern: $A = django.http.HttpResponseBadRequest(..., request.$W[...], ...) + - pattern: return django.http.HttpResponseBadRequest(..., request.$W[...], ...) + - pattern: django.http.HttpResponseBadRequest(..., $S.format(..., request.$W, ...), ...) + - pattern: django.http.HttpResponseBadRequest(..., $S % request.$W, ...) + - pattern: django.http.HttpResponseBadRequest(..., f"...{request.$W}...", ...) + - pattern: django.http.HttpResponseBadRequest(..., request.$W, ...) + - pattern: | + $DATA = request.$W + ... + django.http.HttpResponseBadRequest(..., $DATA, ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = $DATA + ... + django.http.HttpResponseBadRequest(..., $INTERM, ...) + - pattern: | + $DATA = request.$W + ... + django.http.HttpResponseBadRequest(..., $STR.format(..., $DATA, ...), ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = $STR.format(..., $DATA, ...) + ... + django.http.HttpResponseBadRequest(..., $INTERM, ...) + - pattern: | + $DATA = request.$W + ... + django.http.HttpResponseBadRequest(..., $STR % $DATA, ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = $STR % $DATA + ... + django.http.HttpResponseBadRequest(..., $INTERM, ...) + - pattern: | + $DATA = request.$W + ... + django.http.HttpResponseBadRequest(..., f"...{$DATA}...", ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = f"...{$DATA}..." + ... + django.http.HttpResponseBadRequest(..., $INTERM, ...) + - pattern: | + $DATA = request.$W + ... + django.http.HttpResponseBadRequest(..., $STR + $DATA, ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = $STR + $DATA + ... + django.http.HttpResponseBadRequest(..., $INTERM, ...) + - pattern: $A = django.http.HttpResponseBadRequest(..., request.$W, ...) + - pattern: return django.http.HttpResponseBadRequest(..., request.$W, ...) +- id: python.django.security.injection.request-data-fileresponse.request-data-fileresponse + message: Found user-controlled request data being passed into a file open, which is them passed as an + argument into the FileResponse. This is dangerous because an attacker could specify an arbitrary + file to read, which could result in leaking important data. Be sure to validate or sanitize the user-inputted + filename in the request data before using it in FileResponse. + metadata: + cwe: + - "CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')" + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + references: + - https://django-book.readthedocs.io/en/latest/chapter20.html#cross-site-scripting-xss + category: security + technology: + - django + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: LOW + impact: MEDIUM + confidence: MEDIUM + languages: [python] + severity: WARNING + patterns: + - pattern-inside: | + def $FUNC(...): + ... + - pattern-either: + - pattern: django.http.FileResponse(..., request.$W.get(...), ...) + - pattern: | + $DATA = request.$W.get(...) + ... + django.http.FileResponse(..., open($DATA, ...), ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = open($DATA, ...) + ... + django.http.FileResponse(..., $INTERM, ...) + - pattern: $A = django.http.FileResponse(..., request.$W.get(...), ...) + - pattern: return django.http.FileResponse(..., request.$W.get(...), ...) + - pattern: django.http.FileResponse(..., request.$W(...), ...) + - pattern: | + $DATA = request.$W(...) + ... + django.http.FileResponse(..., open($DATA, ...), ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = open($DATA, ...) + ... + django.http.FileResponse(..., $INTERM, ...) + - pattern: $A = django.http.FileResponse(..., request.$W(...), ...) + - pattern: return django.http.FileResponse(..., request.$W(...), ...) + - pattern: django.http.FileResponse(..., request.$W[...], ...) + - pattern: | + $DATA = request.$W[...] + ... + django.http.FileResponse(..., open($DATA, ...), ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = open($DATA, ...) + ... + django.http.FileResponse(..., $INTERM, ...) + - pattern: $A = django.http.FileResponse(..., request.$W[...], ...) + - pattern: return django.http.FileResponse(..., request.$W[...], ...) + - pattern: django.http.FileResponse(..., request.$W, ...) + - pattern: | + $DATA = request.$W + ... + django.http.FileResponse(..., open($DATA, ...), ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = open($DATA, ...) + ... + django.http.FileResponse(..., $INTERM, ...) + - pattern: $A = django.http.FileResponse(..., request.$W, ...) + - pattern: return django.http.FileResponse(..., request.$W, ...) +- id: python.django.security.injection.request-data-write.request-data-write + message: >- + Found user-controlled request data passed into '.write(...)'. This could be dangerous + if a malicious actor is able to control data into sensitive files. For example, + a malicious actor could force rolling of critical log files, or cause a denial-of-service + by using up available disk space. Instead, ensure that request data is properly + escaped or sanitized. + metadata: + cwe: + - "CWE-93: Improper Neutralization of CRLF Sequences ('CRLF Injection')" + owasp: + - A03:2021 - Injection + category: security + technology: + - django + references: + - https://owasp.org/Top10/A03_2021-Injection + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + languages: [python] + severity: WARNING + pattern-either: + - pattern: $F.write(..., request.$W.get(...), ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $F.write(..., $DATA, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = $DATA + ... + $F.write(..., $INTERM, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $F.write(..., $B.$C(..., $DATA, ...), ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = $B.$C(..., $DATA, ...) + ... + $F.write(..., $INTERM, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $F.write(..., $STR % $DATA, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = $STR % $DATA + ... + $F.write(..., $INTERM, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $F.write(..., f"...{$DATA}...", ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = f"...{$DATA}..." + ... + $F.write(..., $INTERM, ...) + - pattern: $A = $F.write(..., request.$W.get(...), ...) + - pattern: return $F.write(..., request.$W.get(...), ...) + - pattern: $F.write(..., request.$W(...), ...) + - pattern: | + $DATA = request.$W(...) + ... + $F.write(..., $DATA, ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = $DATA + ... + $F.write(..., $INTERM, ...) + - pattern: | + $DATA = request.$W(...) + ... + $F.write(..., $B.$C(..., $DATA, ...), ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = $B.$C(..., $DATA, ...) + ... + $F.write(..., $INTERM, ...) + - pattern: | + $DATA = request.$W(...) + ... + $F.write(..., $STR % $DATA, ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = $STR % $DATA + ... + $F.write(..., $INTERM, ...) + - pattern: | + $DATA = request.$W(...) + ... + $F.write(..., f"...{$DATA}...", ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = f"...{$DATA}..." + ... + $F.write(..., $INTERM, ...) + - pattern: $A = $F.write(..., request.$W(...), ...) + - pattern: return $F.write(..., request.$W(...), ...) + - pattern: $F.write(..., request.$W[...], ...) + - pattern: | + $DATA = request.$W[...] + ... + $F.write(..., $DATA, ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = $DATA + ... + $F.write(..., $INTERM, ...) + - pattern: | + $DATA = request.$W[...] + ... + $F.write(..., $B.$C(..., $DATA, ...), ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = $B.$C(..., $DATA, ...) + ... + $F.write(..., $INTERM, ...) + - pattern: | + $DATA = request.$W[...] + ... + $F.write(..., $STR % $DATA, ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = $STR % $DATA + ... + $F.write(..., $INTERM, ...) + - pattern: | + $DATA = request.$W[...] + ... + $F.write(..., f"...{$DATA}...", ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = f"...{$DATA}..." + ... + $F.write(..., $INTERM, ...) + - pattern: $A = $F.write(..., request.$W[...], ...) + - pattern: return $F.write(..., request.$W[...], ...) + - pattern: $F.write(..., request.$W, ...) + - pattern: | + $DATA = request.$W + ... + $F.write(..., $DATA, ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = $DATA + ... + $F.write(..., $INTERM, ...) + - pattern: | + $DATA = request.$W + ... + $F.write(..., $B.$C(..., $DATA, ...), ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = $B.$C(..., $DATA, ...) + ... + $F.write(..., $INTERM, ...) + - pattern: | + $DATA = request.$W + ... + $F.write(..., $STR % $DATA, ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = $STR % $DATA + ... + $F.write(..., $INTERM, ...) + - pattern: | + $DATA = request.$W + ... + $F.write(..., f"...{$DATA}...", ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = f"...{$DATA}..." + ... + $F.write(..., $INTERM, ...) + - pattern: $A = $F.write(..., request.$W, ...) + - pattern: return $F.write(..., request.$W, ...) +- id: python.django.security.injection.sql.sql-injection-extra.sql-injection-using-extra-where + message: User-controlled data from a request is passed to 'extra()'. This could lead to a SQL injection + and therefore protected information could be leaked. Instead, use parameterized queries or escape + the user-controlled data by using `params` and not using quote placeholders in the SQL string. + metadata: + cwe: + - "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')" + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + references: + - https://docs.djangoproject.com/en/3.0/ref/models/expressions/#.objects.extra + category: security + technology: + - django + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: HIGH + confidence: MEDIUM + languages: [python] + severity: WARNING + patterns: + - pattern-inside: | + def $FUNC(...): + ... + - pattern-either: + - pattern: $MODEL.objects.extra(..., where=[..., $S.format(..., request.$W.get(...), ...), ...], ...) + - pattern: $MODEL.objects.extra(..., where=[..., $S % request.$W.get(...), ...], ...) + - pattern: $MODEL.objects.extra(..., where=[..., f"...{request.$W.get(...)}...", ...], ...) + - pattern: $MODEL.objects.extra(..., where=[..., request.$W.get(...), ...], ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $MODEL.objects.extra(..., where=[..., $DATA, ...], ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = $DATA + ... + $MODEL.objects.extra(..., where=[..., $INTERM, ...], ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $MODEL.objects.extra(..., where=[..., $STR.format(..., $DATA, ...), ...], ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = $STR.format(..., $DATA, ...) + ... + $MODEL.objects.extra(..., where=[..., $INTERM, ...], ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $MODEL.objects.extra(..., where=[..., $STR % $DATA, ...], ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = $STR % $DATA + ... + $MODEL.objects.extra(..., where=[..., $INTERM, ...], ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $MODEL.objects.extra(..., where=[..., f"...{$DATA}...", ...], ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = f"...{$DATA}..." + ... + $MODEL.objects.extra(..., where=[..., $INTERM, ...], ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $MODEL.objects.extra(..., where=[..., $STR + $DATA, ...], ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = $STR + $DATA + ... + $MODEL.objects.extra(..., where=[..., $INTERM, ...], ...) + - pattern: $A = $MODEL.objects.extra(..., where=[..., request.$W.get(...), ...], ...) + - pattern: return $MODEL.objects.extra(..., where=[..., request.$W.get(...), ...], ...) + - pattern: $MODEL.objects.extra(..., where=[..., $S.format(..., request.$W(...), ...), ...], ...) + - pattern: $MODEL.objects.extra(..., where=[..., $S % request.$W(...), ...], ...) + - pattern: $MODEL.objects.extra(..., where=[..., f"...{request.$W(...)}...", ...], ...) + - pattern: $MODEL.objects.extra(..., where=[..., request.$W(...), ...], ...) + - pattern: | + $DATA = request.$W(...) + ... + $MODEL.objects.extra(..., where=[..., $DATA, ...], ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = $DATA + ... + $MODEL.objects.extra(..., where=[..., $INTERM, ...], ...) + - pattern: | + $DATA = request.$W(...) + ... + $MODEL.objects.extra(..., where=[..., $STR.format(..., $DATA, ...), ...], ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = $STR.format(..., $DATA, ...) + ... + $MODEL.objects.extra(..., where=[..., $INTERM, ...], ...) + - pattern: | + $DATA = request.$W(...) + ... + $MODEL.objects.extra(..., where=[..., $STR % $DATA, ...], ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = $STR % $DATA + ... + $MODEL.objects.extra(..., where=[..., $INTERM, ...], ...) + - pattern: | + $DATA = request.$W(...) + ... + $MODEL.objects.extra(..., where=[..., f"...{$DATA}...", ...], ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = f"...{$DATA}..." + ... + $MODEL.objects.extra(..., where=[..., $INTERM, ...], ...) + - pattern: | + $DATA = request.$W(...) + ... + $MODEL.objects.extra(..., where=[..., $STR + $DATA, ...], ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = $STR + $DATA + ... + $MODEL.objects.extra(..., where=[..., $INTERM, ...], ...) + - pattern: $A = $MODEL.objects.extra(..., where=[..., request.$W(...), ...], ...) + - pattern: return $MODEL.objects.extra(..., where=[..., request.$W(...), ...], ...) + - pattern: $MODEL.objects.extra(..., where=[..., $S.format(..., request.$W[...], ...), ...], ...) + - pattern: $MODEL.objects.extra(..., where=[..., $S % request.$W[...], ...], ...) + - pattern: $MODEL.objects.extra(..., where=[..., f"...{request.$W[...]}...", ...], ...) + - pattern: $MODEL.objects.extra(..., where=[..., request.$W[...], ...], ...) + - pattern: | + $DATA = request.$W[...] + ... + $MODEL.objects.extra(..., where=[..., $DATA, ...], ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = $DATA + ... + $MODEL.objects.extra(..., where=[..., $INTERM, ...], ...) + - pattern: | + $DATA = request.$W[...] + ... + $MODEL.objects.extra(..., where=[..., $STR.format(..., $DATA, ...), ...], ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = $STR.format(..., $DATA, ...) + ... + $MODEL.objects.extra(..., where=[..., $INTERM, ...], ...) + - pattern: | + $DATA = request.$W[...] + ... + $MODEL.objects.extra(..., where=[..., $STR % $DATA, ...], ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = $STR % $DATA + ... + $MODEL.objects.extra(..., where=[..., $INTERM, ...], ...) + - pattern: | + $DATA = request.$W[...] + ... + $MODEL.objects.extra(..., where=[..., f"...{$DATA}...", ...], ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = f"...{$DATA}..." + ... + $MODEL.objects.extra(..., where=[..., $INTERM, ...], ...) + - pattern: | + $DATA = request.$W[...] + ... + $MODEL.objects.extra(..., where=[..., $STR + $DATA, ...], ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = $STR + $DATA + ... + $MODEL.objects.extra(..., where=[..., $INTERM, ...], ...) + - pattern: $A = $MODEL.objects.extra(..., where=[..., request.$W[...], ...], ...) + - pattern: return $MODEL.objects.extra(..., where=[..., request.$W[...], ...], ...) + - pattern: $MODEL.objects.extra(..., where=[..., $S.format(..., request.$W, ...), ...], ...) + - pattern: $MODEL.objects.extra(..., where=[..., $S % request.$W, ...], ...) + - pattern: $MODEL.objects.extra(..., where=[..., f"...{request.$W}...", ...], ...) + - pattern: $MODEL.objects.extra(..., where=[..., request.$W, ...], ...) + - pattern: | + $DATA = request.$W + ... + $MODEL.objects.extra(..., where=[..., $DATA, ...], ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = $DATA + ... + $MODEL.objects.extra(..., where=[..., $INTERM, ...], ...) + - pattern: | + $DATA = request.$W + ... + $MODEL.objects.extra(..., where=[..., $STR.format(..., $DATA, ...), ...], ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = $STR.format(..., $DATA, ...) + ... + $MODEL.objects.extra(..., where=[..., $INTERM, ...], ...) + - pattern: | + $DATA = request.$W + ... + $MODEL.objects.extra(..., where=[..., $STR % $DATA, ...], ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = $STR % $DATA + ... + $MODEL.objects.extra(..., where=[..., $INTERM, ...], ...) + - pattern: | + $DATA = request.$W + ... + $MODEL.objects.extra(..., where=[..., f"...{$DATA}...", ...], ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = f"...{$DATA}..." + ... + $MODEL.objects.extra(..., where=[..., $INTERM, ...], ...) + - pattern: | + $DATA = request.$W + ... + $MODEL.objects.extra(..., where=[..., $STR + $DATA, ...], ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = $STR + $DATA + ... + $MODEL.objects.extra(..., where=[..., $INTERM, ...], ...) + - pattern: $A = $MODEL.objects.extra(..., where=[..., request.$W, ...], ...) + - pattern: return $MODEL.objects.extra(..., where=[..., request.$W, ...], ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $MODEL.objects.extra(..., where=[..., $STR % (..., $DATA, ...), ...], ...) + - pattern: | + $DATA = request.$W[...] + ... + $MODEL.objects.extra(..., where=[..., $STR % (..., $DATA, ...), ...], ...) + - pattern: | + $DATA = request.$W(...) + ... + $MODEL.objects.extra(..., where=[..., $STR % (..., $DATA, ...), ...], ...) + - pattern: | + $DATA = request.$W + ... + $MODEL.objects.extra(..., where=[..., $STR % (..., $DATA, ...), ...], ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = $STR % (..., $DATA, ...) + ... + $MODEL.objects.extra(..., where=[..., $INTERM, ...], ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = $STR % (..., $DATA, ...) + ... + $MODEL.objects.extra(..., where=[..., $INTERM, ...], ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = $STR % (..., $DATA, ...) + ... + $MODEL.objects.extra(..., where=[..., $INTERM, ...], ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = $STR % (..., $DATA, ...) + ... + $MODEL.objects.extra(..., where=[..., $INTERM, ...], ...) +- id: python.django.security.injection.sql.sql-injection-rawsql.sql-injection-using-rawsql + message: User-controlled data from request is passed to 'RawSQL()'. This could lead to a SQL injection + and therefore protected information could be leaked. Instead, use parameterized queries or escape + the user-controlled data by using `params` and not using quote placeholders in the SQL string. + metadata: + cwe: + - "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')" + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + references: + - https://docs.djangoproject.com/en/3.0/ref/models/expressions/#django.db.models.expressions.RawSQL + category: security + technology: + - django + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: HIGH + confidence: MEDIUM + languages: [python] + severity: WARNING + patterns: + - pattern-inside: | + def $FUNC(...): + ... + - pattern-either: + - pattern: django.db.models.expressions.RawSQL(..., $S.format(..., request.$W.get(...), ...), ...) + - pattern: django.db.models.expressions.RawSQL(..., $S % request.$W.get(...), ...) + - pattern: django.db.models.expressions.RawSQL(..., f"...{request.$W.get(...)}...", ...) + - pattern: django.db.models.expressions.RawSQL(..., request.$W.get(...), ...) + - pattern: | + $DATA = request.$W.get(...) + ... + django.db.models.expressions.RawSQL(..., $DATA, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = $DATA + ... + django.db.models.expressions.RawSQL(..., $INTERM, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + django.db.models.expressions.RawSQL(..., $STR.format(..., $DATA, ...), ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = $STR.format(..., $DATA, ...) + ... + django.db.models.expressions.RawSQL(..., $INTERM, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + django.db.models.expressions.RawSQL(..., $STR % $DATA, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = $STR % $DATA + ... + django.db.models.expressions.RawSQL(..., $INTERM, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + django.db.models.expressions.RawSQL(..., f"...{$DATA}...", ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = f"...{$DATA}..." + ... + django.db.models.expressions.RawSQL(..., $INTERM, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + django.db.models.expressions.RawSQL(..., $STR + $DATA, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = $STR + $DATA + ... + django.db.models.expressions.RawSQL(..., $INTERM, ...) + - pattern: $A = django.db.models.expressions.RawSQL(..., request.$W.get(...), ...) + - pattern: return django.db.models.expressions.RawSQL(..., request.$W.get(...), ...) + - pattern: django.db.models.expressions.RawSQL(..., $S.format(..., request.$W(...), ...), ...) + - pattern: django.db.models.expressions.RawSQL(..., $S % request.$W(...), ...) + - pattern: django.db.models.expressions.RawSQL(..., f"...{request.$W(...)}...", ...) + - pattern: django.db.models.expressions.RawSQL(..., request.$W(...), ...) + - pattern: | + $DATA = request.$W(...) + ... + django.db.models.expressions.RawSQL(..., $DATA, ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = $DATA + ... + django.db.models.expressions.RawSQL(..., $INTERM, ...) + - pattern: | + $DATA = request.$W(...) + ... + django.db.models.expressions.RawSQL(..., $STR.format(..., $DATA, ...), ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = $STR.format(..., $DATA, ...) + ... + django.db.models.expressions.RawSQL(..., $INTERM, ...) + - pattern: | + $DATA = request.$W(...) + ... + django.db.models.expressions.RawSQL(..., $STR % $DATA, ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = $STR % $DATA + ... + django.db.models.expressions.RawSQL(..., $INTERM, ...) + - pattern: | + $DATA = request.$W(...) + ... + django.db.models.expressions.RawSQL(..., f"...{$DATA}...", ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = f"...{$DATA}..." + ... + django.db.models.expressions.RawSQL(..., $INTERM, ...) + - pattern: | + $DATA = request.$W(...) + ... + django.db.models.expressions.RawSQL(..., $STR + $DATA, ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = $STR + $DATA + ... + django.db.models.expressions.RawSQL(..., $INTERM, ...) + - pattern: $A = django.db.models.expressions.RawSQL(..., request.$W(...), ...) + - pattern: return django.db.models.expressions.RawSQL(..., request.$W(...), ...) + - pattern: django.db.models.expressions.RawSQL(..., $S.format(..., request.$W[...], ...), ...) + - pattern: django.db.models.expressions.RawSQL(..., $S % request.$W[...], ...) + - pattern: django.db.models.expressions.RawSQL(..., f"...{request.$W[...]}...", ...) + - pattern: django.db.models.expressions.RawSQL(..., request.$W[...], ...) + - pattern: | + $DATA = request.$W[...] + ... + django.db.models.expressions.RawSQL(..., $DATA, ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = $DATA + ... + django.db.models.expressions.RawSQL(..., $INTERM, ...) + - pattern: | + $DATA = request.$W[...] + ... + django.db.models.expressions.RawSQL(..., $STR.format(..., $DATA, ...), ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = $STR.format(..., $DATA, ...) + ... + django.db.models.expressions.RawSQL(..., $INTERM, ...) + - pattern: | + $DATA = request.$W[...] + ... + django.db.models.expressions.RawSQL(..., $STR % $DATA, ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = $STR % $DATA + ... + django.db.models.expressions.RawSQL(..., $INTERM, ...) + - pattern: | + $DATA = request.$W[...] + ... + django.db.models.expressions.RawSQL(..., f"...{$DATA}...", ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = f"...{$DATA}..." + ... + django.db.models.expressions.RawSQL(..., $INTERM, ...) + - pattern: | + $DATA = request.$W[...] + ... + django.db.models.expressions.RawSQL(..., $STR + $DATA, ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = $STR + $DATA + ... + django.db.models.expressions.RawSQL(..., $INTERM, ...) + - pattern: $A = django.db.models.expressions.RawSQL(..., request.$W[...], ...) + - pattern: return django.db.models.expressions.RawSQL(..., request.$W[...], ...) + - pattern: django.db.models.expressions.RawSQL(..., $S.format(..., request.$W, ...), ...) + - pattern: django.db.models.expressions.RawSQL(..., $S % request.$W, ...) + - pattern: django.db.models.expressions.RawSQL(..., f"...{request.$W}...", ...) + - pattern: django.db.models.expressions.RawSQL(..., request.$W, ...) + - pattern: | + $DATA = request.$W + ... + django.db.models.expressions.RawSQL(..., $DATA, ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = $DATA + ... + django.db.models.expressions.RawSQL(..., $INTERM, ...) + - pattern: | + $DATA = request.$W + ... + django.db.models.expressions.RawSQL(..., $STR.format(..., $DATA, ...), ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = $STR.format(..., $DATA, ...) + ... + django.db.models.expressions.RawSQL(..., $INTERM, ...) + - pattern: | + $DATA = request.$W + ... + django.db.models.expressions.RawSQL(..., $STR % $DATA, ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = $STR % $DATA + ... + django.db.models.expressions.RawSQL(..., $INTERM, ...) + - pattern: | + $DATA = request.$W + ... + django.db.models.expressions.RawSQL(..., f"...{$DATA}...", ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = f"...{$DATA}..." + ... + django.db.models.expressions.RawSQL(..., $INTERM, ...) + - pattern: | + $DATA = request.$W + ... + django.db.models.expressions.RawSQL(..., $STR + $DATA, ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = $STR + $DATA + ... + django.db.models.expressions.RawSQL(..., $INTERM, ...) + - pattern: $A = django.db.models.expressions.RawSQL(..., request.$W, ...) + - pattern: return django.db.models.expressions.RawSQL(..., request.$W, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + django.db.models.expressions.RawSQL($STR % (..., $DATA, ...), ...) + - pattern: | + $DATA = request.$W[...] + ... + django.db.models.expressions.RawSQL($STR % (..., $DATA, ...), ...) + - pattern: | + $DATA = request.$W(...) + ... + django.db.models.expressions.RawSQL($STR % (..., $DATA, ...), ...) + - pattern: | + $DATA = request.$W + ... + django.db.models.expressions.RawSQL($STR % (..., $DATA, ...), ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = $STR % (..., $DATA, ...) + ... + django.db.models.expressions.RawSQL($INTERM, ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = $STR % (..., $DATA, ...) + ... + django.db.models.expressions.RawSQL($INTERM, ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = $STR % (..., $DATA, ...) + ... + django.db.models.expressions.RawSQL($INTERM, ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = $STR % (..., $DATA, ...) + ... + django.db.models.expressions.RawSQL($INTERM, ...) +- id: python.django.security.injection.sql.sql-injection-using-db-cursor-execute.sql-injection-db-cursor-execute + message: User-controlled data from a request is passed to 'execute()'. This could lead to a SQL injection + and therefore protected information could be leaked. Instead, use django's QuerySets, which are built + with query parameterization and therefore not vulnerable to sql injection. For example, you could + use `Entry.objects.filter(date=2006)`. + metadata: + cwe: + - "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')" + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + references: + - https://docs.djangoproject.com/en/3.0/topics/security/#sql-injection-protection + category: security + technology: + - django + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: HIGH + confidence: MEDIUM + languages: [python] + severity: WARNING + patterns: + - pattern-inside: | + def $FUNC(...): + ... + - pattern-either: + - pattern: $CURSOR.execute(..., $S.format(..., request.$W.get(...), ...), ...) + - pattern: $CURSOR.execute(..., $S % request.$W.get(...), ...) + - pattern: $CURSOR.execute(..., f"...{request.$W.get(...)}...", ...) + - pattern: $CURSOR.execute(..., request.$W.get(...), ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $CURSOR.execute(..., $DATA, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = $DATA + ... + $CURSOR.execute(..., $INTERM, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $CURSOR.execute(..., $STR.format(..., $DATA, ...), ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = $STR.format(..., $DATA, ...) + ... + $CURSOR.execute(..., $INTERM, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $CURSOR.execute(..., $STR % $DATA, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = $STR % $DATA + ... + $CURSOR.execute(..., $INTERM, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $CURSOR.execute(..., f"...{$DATA}...", ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = f"...{$DATA}..." + ... + $CURSOR.execute(..., $INTERM, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $CURSOR.execute(..., $STR + $DATA, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = $STR + $DATA + ... + $CURSOR.execute(..., $INTERM, ...) + - pattern: $A = $CURSOR.execute(..., request.$W.get(...), ...) + - pattern: return $CURSOR.execute(..., request.$W.get(...), ...) + - pattern: $CURSOR.execute(..., $S.format(..., request.$W(...), ...), ...) + - pattern: $CURSOR.execute(..., $S % request.$W(...), ...) + - pattern: $CURSOR.execute(..., f"...{request.$W(...)}...", ...) + - pattern: $CURSOR.execute(..., request.$W(...), ...) + - pattern: | + $DATA = request.$W(...) + ... + $CURSOR.execute(..., $DATA, ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = $DATA + ... + $CURSOR.execute(..., $INTERM, ...) + - pattern: | + $DATA = request.$W(...) + ... + $CURSOR.execute(..., $STR.format(..., $DATA, ...), ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = $STR.format(..., $DATA, ...) + ... + $CURSOR.execute(..., $INTERM, ...) + - pattern: | + $DATA = request.$W(...) + ... + $CURSOR.execute(..., $STR % $DATA, ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = $STR % $DATA + ... + $CURSOR.execute(..., $INTERM, ...) + - pattern: | + $DATA = request.$W(...) + ... + $CURSOR.execute(..., f"...{$DATA}...", ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = f"...{$DATA}..." + ... + $CURSOR.execute(..., $INTERM, ...) + - pattern: | + $DATA = request.$W(...) + ... + $CURSOR.execute(..., $STR + $DATA, ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = $STR + $DATA + ... + $CURSOR.execute(..., $INTERM, ...) + - pattern: $A = $CURSOR.execute(..., request.$W(...), ...) + - pattern: return $CURSOR.execute(..., request.$W(...), ...) + - pattern: $CURSOR.execute(..., $S.format(..., request.$W[...], ...), ...) + - pattern: $CURSOR.execute(..., $S % request.$W[...], ...) + - pattern: $CURSOR.execute(..., f"...{request.$W[...]}...", ...) + - pattern: $CURSOR.execute(..., request.$W[...], ...) + - pattern: | + $DATA = request.$W[...] + ... + $CURSOR.execute(..., $DATA, ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = $DATA + ... + $CURSOR.execute(..., $INTERM, ...) + - pattern: | + $DATA = request.$W[...] + ... + $CURSOR.execute(..., $STR.format(..., $DATA, ...), ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = $STR.format(..., $DATA, ...) + ... + $CURSOR.execute(..., $INTERM, ...) + - pattern: | + $DATA = request.$W[...] + ... + $CURSOR.execute(..., $STR % $DATA, ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = $STR % $DATA + ... + $CURSOR.execute(..., $INTERM, ...) + - pattern: | + $DATA = request.$W[...] + ... + $CURSOR.execute(..., f"...{$DATA}...", ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = f"...{$DATA}..." + ... + $CURSOR.execute(..., $INTERM, ...) + - pattern: | + $DATA = request.$W[...] + ... + $CURSOR.execute(..., $STR + $DATA, ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = $STR + $DATA + ... + $CURSOR.execute(..., $INTERM, ...) + - pattern: $A = $CURSOR.execute(..., request.$W[...], ...) + - pattern: return $CURSOR.execute(..., request.$W[...], ...) + - pattern: $CURSOR.execute(..., $S.format(..., request.$W, ...), ...) + - pattern: $CURSOR.execute(..., $S % request.$W, ...) + - pattern: $CURSOR.execute(..., f"...{request.$W}...", ...) + - pattern: $CURSOR.execute(..., request.$W, ...) + - pattern: | + $DATA = request.$W + ... + $CURSOR.execute(..., $DATA, ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = $DATA + ... + $CURSOR.execute(..., $INTERM, ...) + - pattern: | + $DATA = request.$W + ... + $CURSOR.execute(..., $STR.format(..., $DATA, ...), ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = $STR.format(..., $DATA, ...) + ... + $CURSOR.execute(..., $INTERM, ...) + - pattern: | + $DATA = request.$W + ... + $CURSOR.execute(..., $STR % $DATA, ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = $STR % $DATA + ... + $CURSOR.execute(..., $INTERM, ...) + - pattern: | + $DATA = request.$W + ... + $CURSOR.execute(..., f"...{$DATA}...", ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = f"...{$DATA}..." + ... + $CURSOR.execute(..., $INTERM, ...) + - pattern: | + $DATA = request.$W + ... + $CURSOR.execute(..., $STR + $DATA, ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = $STR + $DATA + ... + $CURSOR.execute(..., $INTERM, ...) + - pattern: $A = $CURSOR.execute(..., request.$W, ...) + - pattern: return $CURSOR.execute(..., request.$W, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $CURSOR.execute($STR % (..., $DATA, ...), ...) + - pattern: | + $DATA = request.$W[...] + ... + $CURSOR.execute($STR % (..., $DATA, ...), ...) + - pattern: | + $DATA = request.$W(...) + ... + $CURSOR.execute($STR % (..., $DATA, ...), ...) + - pattern: | + $DATA = request.$W + ... + $CURSOR.execute($STR % (..., $DATA, ...), ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = $STR % (..., $DATA, ...) + ... + $CURSOR.execute($INTERM, ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = $STR % (..., $DATA, ...) + ... + $CURSOR.execute($INTERM, ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = $STR % (..., $DATA, ...) + ... + $CURSOR.execute($INTERM, ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = $STR % (..., $DATA, ...) + ... + $CURSOR.execute($INTERM, ...) +- id: python.django.security.injection.sql.sql-injection-using-raw.sql-injection-using-raw + message: Data that is possible user-controlled from a python request is passed to `raw()`. This could + lead to SQL injection and attackers gaining access to protected information. Instead, use django's + QuerySets, which are built with query parameterization and therefore not vulnerable to sql injection. + For example, you could use `Entry.objects.filter(date=2006)`. + metadata: + cwe: + - "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')" + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + references: + - https://docs.djangoproject.com/en/3.0/topics/security/#sql-injection-protection + category: security + technology: + - django + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: HIGH + confidence: MEDIUM + languages: [python] + severity: WARNING + patterns: + - pattern-inside: | + def $FUNC(...): + ... + - pattern-either: + - pattern: $MODEL.objects.raw(..., $S.format(..., request.$W.get(...), ...), ...) + - pattern: $MODEL.objects.raw(..., $S % request.$W.get(...), ...) + - pattern: $MODEL.objects.raw(..., f"...{request.$W.get(...)}...", ...) + - pattern: $MODEL.objects.raw(..., request.$W.get(...), ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $MODEL.objects.raw(..., $DATA, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = $DATA + ... + $MODEL.objects.raw(..., $INTERM, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $MODEL.objects.raw(..., $STR.format(..., $DATA, ...), ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = $STR.format(..., $DATA, ...) + ... + $MODEL.objects.raw(..., $INTERM, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $MODEL.objects.raw(..., $STR % $DATA, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = $STR % $DATA + ... + $MODEL.objects.raw(..., $INTERM, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $MODEL.objects.raw(..., f"...{$DATA}...", ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = f"...{$DATA}..." + ... + $MODEL.objects.raw(..., $INTERM, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $MODEL.objects.raw(..., $STR + $DATA, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = $STR + $DATA + ... + $MODEL.objects.raw(..., $INTERM, ...) + - pattern: $A = $MODEL.objects.raw(..., request.$W.get(...), ...) + - pattern: return $MODEL.objects.raw(..., request.$W.get(...), ...) + - pattern: $MODEL.objects.raw(..., $S.format(..., request.$W(...), ...), ...) + - pattern: $MODEL.objects.raw(..., $S % request.$W(...), ...) + - pattern: $MODEL.objects.raw(..., f"...{request.$W(...)}...", ...) + - pattern: $MODEL.objects.raw(..., request.$W(...), ...) + - pattern: | + $DATA = request.$W(...) + ... + $MODEL.objects.raw(..., $DATA, ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = $DATA + ... + $MODEL.objects.raw(..., $INTERM, ...) + - pattern: | + $DATA = request.$W(...) + ... + $MODEL.objects.raw(..., $STR.format(..., $DATA, ...), ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = $STR.format(..., $DATA, ...) + ... + $MODEL.objects.raw(..., $INTERM, ...) + - pattern: | + $DATA = request.$W(...) + ... + $MODEL.objects.raw(..., $STR % $DATA, ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = $STR % $DATA + ... + $MODEL.objects.raw(..., $INTERM, ...) + - pattern: | + $DATA = request.$W(...) + ... + $MODEL.objects.raw(..., f"...{$DATA}...", ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = f"...{$DATA}..." + ... + $MODEL.objects.raw(..., $INTERM, ...) + - pattern: | + $DATA = request.$W(...) + ... + $MODEL.objects.raw(..., $STR + $DATA, ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = $STR + $DATA + ... + $MODEL.objects.raw(..., $INTERM, ...) + - pattern: $A = $MODEL.objects.raw(..., request.$W(...), ...) + - pattern: return $MODEL.objects.raw(..., request.$W(...), ...) + - pattern: $MODEL.objects.raw(..., $S.format(..., request.$W[...], ...), ...) + - pattern: $MODEL.objects.raw(..., $S % request.$W[...], ...) + - pattern: $MODEL.objects.raw(..., f"...{request.$W[...]}...", ...) + - pattern: $MODEL.objects.raw(..., request.$W[...], ...) + - pattern: | + $DATA = request.$W[...] + ... + $MODEL.objects.raw(..., $DATA, ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = $DATA + ... + $MODEL.objects.raw(..., $INTERM, ...) + - pattern: | + $DATA = request.$W[...] + ... + $MODEL.objects.raw(..., $STR.format(..., $DATA, ...), ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = $STR.format(..., $DATA, ...) + ... + $MODEL.objects.raw(..., $INTERM, ...) + - pattern: | + $DATA = request.$W[...] + ... + $MODEL.objects.raw(..., $STR % $DATA, ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = $STR % $DATA + ... + $MODEL.objects.raw(..., $INTERM, ...) + - pattern: | + $DATA = request.$W[...] + ... + $MODEL.objects.raw(..., f"...{$DATA}...", ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = f"...{$DATA}..." + ... + $MODEL.objects.raw(..., $INTERM, ...) + - pattern: | + $DATA = request.$W[...] + ... + $MODEL.objects.raw(..., $STR + $DATA, ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = $STR + $DATA + ... + $MODEL.objects.raw(..., $INTERM, ...) + - pattern: $A = $MODEL.objects.raw(..., request.$W[...], ...) + - pattern: return $MODEL.objects.raw(..., request.$W[...], ...) + - pattern: $MODEL.objects.raw(..., $S.format(..., request.$W, ...), ...) + - pattern: $MODEL.objects.raw(..., $S % request.$W, ...) + - pattern: $MODEL.objects.raw(..., f"...{request.$W}...", ...) + - pattern: $MODEL.objects.raw(..., request.$W, ...) + - pattern: | + $DATA = request.$W + ... + $MODEL.objects.raw(..., $DATA, ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = $DATA + ... + $MODEL.objects.raw(..., $INTERM, ...) + - pattern: | + $DATA = request.$W + ... + $MODEL.objects.raw(..., $STR.format(..., $DATA, ...), ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = $STR.format(..., $DATA, ...) + ... + $MODEL.objects.raw(..., $INTERM, ...) + - pattern: | + $DATA = request.$W + ... + $MODEL.objects.raw(..., $STR % $DATA, ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = $STR % $DATA + ... + $MODEL.objects.raw(..., $INTERM, ...) + - pattern: | + $DATA = request.$W + ... + $MODEL.objects.raw(..., f"...{$DATA}...", ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = f"...{$DATA}..." + ... + $MODEL.objects.raw(..., $INTERM, ...) + - pattern: | + $DATA = request.$W + ... + $MODEL.objects.raw(..., $STR + $DATA, ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = $STR + $DATA + ... + $MODEL.objects.raw(..., $INTERM, ...) + - pattern: $A = $MODEL.objects.raw(..., request.$W, ...) + - pattern: return $MODEL.objects.raw(..., request.$W, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $MODEL.objects.raw($STR % (..., $DATA, ...), ...) + - pattern: | + $DATA = request.$W[...] + ... + $MODEL.objects.raw($STR % (..., $DATA, ...), ...) + - pattern: | + $DATA = request.$W(...) + ... + $MODEL.objects.raw($STR % (..., $DATA, ...), ...) + - pattern: | + $DATA = request.$W + ... + $MODEL.objects.raw($STR % (..., $DATA, ...), ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = $STR % (..., $DATA, ...) + ... + $MODEL.objects.raw($INTERM, ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = $STR % (..., $DATA, ...) + ... + $MODEL.objects.raw($INTERM, ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = $STR % (..., $DATA, ...) + ... + $MODEL.objects.raw($INTERM, ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = $STR % (..., $DATA, ...) + ... + $MODEL.objects.raw($INTERM, ...) +- id: python.django.security.injection.ssrf.ssrf-injection-requests.ssrf-injection-requests + message: >- + Data from request object is passed to a new server-side request. + This could lead to a server-side request forgery (SSRF). To mitigate, + ensure that schemes and hosts are validated against an allowlist, + do not forward the response to the user, and ensure proper authentication + and transport-layer security in the proxied request. + See https://owasp.org/www-community/attacks/Server_Side_Request_Forgery to + learn more about SSRF vulnerabilities. + metadata: + cwe: + - 'CWE-918: Server-Side Request Forgery (SSRF)' + owasp: + - A10:2021 - Server-Side Request Forgery (SSRF) + references: + - https://owasp.org/www-community/attacks/Server_Side_Request_Forgery + category: security + technology: + - django + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: HIGH + confidence: MEDIUM + languages: [python] + severity: ERROR + patterns: + - pattern-inside: | + def $FUNC(...): + ... + - pattern-either: + - pattern: requests.$METHOD(..., $S.format(..., request.$W.get(...), ...), ...) + - pattern: requests.$METHOD(..., $S % request.$W.get(...), ...) + - pattern: requests.$METHOD(..., f"...{request.$W.get(...)}...", ...) + - pattern: requests.$METHOD(..., request.$W.get(...), ...) + - pattern: | + $DATA = request.$W.get(...) + ... + requests.$METHOD(..., $DATA, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = $DATA + ... + requests.$METHOD(..., $INTERM, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + requests.$METHOD(..., $STR.format(..., $DATA, ...), ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = $STR.format(..., $DATA, ...) + ... + requests.$METHOD(..., $INTERM, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + requests.$METHOD(..., $STR % $DATA, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = $STR % $DATA + ... + requests.$METHOD(..., $INTERM, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + requests.$METHOD(..., f"...{$DATA}...", ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = f"...{$DATA}..." + ... + requests.$METHOD(..., $INTERM, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + requests.$METHOD(..., $STR + $DATA, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = $STR + $DATA + ... + requests.$METHOD(..., $INTERM, ...) + - pattern: $A = requests.$METHOD(..., request.$W.get(...), ...) + - pattern: return requests.$METHOD(..., request.$W.get(...), ...) + - pattern: requests.$METHOD(..., $S.format(..., request.$W(...), ...), ...) + - pattern: requests.$METHOD(..., $S % request.$W(...), ...) + - pattern: requests.$METHOD(..., f"...{request.$W(...)}...", ...) + - pattern: requests.$METHOD(..., request.$W(...), ...) + - pattern: | + $DATA = request.$W(...) + ... + requests.$METHOD(..., $DATA, ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = $DATA + ... + requests.$METHOD(..., $INTERM, ...) + - pattern: | + $DATA = request.$W(...) + ... + requests.$METHOD(..., $STR.format(..., $DATA, ...), ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = $STR.format(..., $DATA, ...) + ... + requests.$METHOD(..., $INTERM, ...) + - pattern: | + $DATA = request.$W(...) + ... + requests.$METHOD(..., $STR % $DATA, ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = $STR % $DATA + ... + requests.$METHOD(..., $INTERM, ...) + - pattern: | + $DATA = request.$W(...) + ... + requests.$METHOD(..., f"...{$DATA}...", ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = f"...{$DATA}..." + ... + requests.$METHOD(..., $INTERM, ...) + - pattern: | + $DATA = request.$W(...) + ... + requests.$METHOD(..., $STR + $DATA, ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = $STR + $DATA + ... + requests.$METHOD(..., $INTERM, ...) + - pattern: $A = requests.$METHOD(..., request.$W(...), ...) + - pattern: return requests.$METHOD(..., request.$W(...), ...) + - pattern: requests.$METHOD(..., $S.format(..., request.$W[...], ...), ...) + - pattern: requests.$METHOD(..., $S % request.$W[...], ...) + - pattern: requests.$METHOD(..., f"...{request.$W[...]}...", ...) + - pattern: requests.$METHOD(..., request.$W[...], ...) + - pattern: | + $DATA = request.$W[...] + ... + requests.$METHOD(..., $DATA, ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = $DATA + ... + requests.$METHOD(..., $INTERM, ...) + - pattern: | + $DATA = request.$W[...] + ... + requests.$METHOD(..., $STR.format(..., $DATA, ...), ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = $STR.format(..., $DATA, ...) + ... + requests.$METHOD(..., $INTERM, ...) + - pattern: | + $DATA = request.$W[...] + ... + requests.$METHOD(..., $STR % $DATA, ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = $STR % $DATA + ... + requests.$METHOD(..., $INTERM, ...) + - pattern: | + $DATA = request.$W[...] + ... + requests.$METHOD(..., f"...{$DATA}...", ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = f"...{$DATA}..." + ... + requests.$METHOD(..., $INTERM, ...) + - pattern: | + $DATA = request.$W[...] + ... + requests.$METHOD(..., $STR + $DATA, ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = $STR + $DATA + ... + requests.$METHOD(..., $INTERM, ...) + - pattern: $A = requests.$METHOD(..., request.$W[...], ...) + - pattern: return requests.$METHOD(..., request.$W[...], ...) + - pattern: requests.$METHOD(..., $S.format(..., request.$W, ...), ...) + - pattern: requests.$METHOD(..., $S % request.$W, ...) + - pattern: requests.$METHOD(..., f"...{request.$W}...", ...) + - pattern: requests.$METHOD(..., request.$W, ...) + - pattern: | + $DATA = request.$W + ... + requests.$METHOD(..., $DATA, ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = $DATA + ... + requests.$METHOD(..., $INTERM, ...) + - pattern: | + $DATA = request.$W + ... + requests.$METHOD(..., $STR.format(..., $DATA, ...), ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = $STR.format(..., $DATA, ...) + ... + requests.$METHOD(..., $INTERM, ...) + - pattern: | + $DATA = request.$W + ... + requests.$METHOD(..., $STR % $DATA, ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = $STR % $DATA + ... + requests.$METHOD(..., $INTERM, ...) + - pattern: | + $DATA = request.$W + ... + requests.$METHOD(..., f"...{$DATA}...", ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = f"...{$DATA}..." + ... + requests.$METHOD(..., $INTERM, ...) + - pattern: | + $DATA = request.$W + ... + requests.$METHOD(..., $STR + $DATA, ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = $STR + $DATA + ... + requests.$METHOD(..., $INTERM, ...) + - pattern: $A = requests.$METHOD(..., request.$W, ...) + - pattern: return requests.$METHOD(..., request.$W, ...) +- id: python.django.security.injection.ssrf.ssrf-injection-urllib.ssrf-injection-urllib + message: >- + Data from request object is passed to a new server-side request. This could lead + to a server-side request forgery (SSRF), which could result in attackers gaining + access to private organization data. To mitigate, ensure that schemes and hosts + are validated against an allowlist, do not forward the response to the user, and + ensure proper authentication and transport-layer security in the proxied request. + metadata: + cwe: + - 'CWE-918: Server-Side Request Forgery (SSRF)' + owasp: + - A10:2021 - Server-Side Request Forgery (SSRF) + references: + - https://owasp.org/www-community/attacks/Server_Side_Request_Forgery + category: security + technology: + - django + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: HIGH + confidence: MEDIUM + languages: [python] + severity: ERROR + patterns: + - pattern-inside: | + def $FUNC(...): + ... + - pattern-either: + - pattern: urllib.request.urlopen(..., $S.format(..., request.$W.get(...), ...), ...) + - pattern: urllib.request.urlopen(..., $S % request.$W.get(...), ...) + - pattern: urllib.request.urlopen(..., f"...{request.$W.get(...)}...", ...) + - pattern: urllib.request.urlopen(..., request.$W.get(...), ...) + - pattern: | + $DATA = request.$W.get(...) + ... + urllib.request.urlopen(..., $DATA, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = $DATA + ... + urllib.request.urlopen(..., $INTERM, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + urllib.request.urlopen(..., $STR.format(..., $DATA, ...), ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = $STR.format(..., $DATA, ...) + ... + urllib.request.urlopen(..., $INTERM, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + urllib.request.urlopen(..., $STR % $DATA, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = $STR % $DATA + ... + urllib.request.urlopen(..., $INTERM, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + urllib.request.urlopen(..., f"...{$DATA}...", ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = f"...{$DATA}..." + ... + urllib.request.urlopen(..., $INTERM, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + urllib.request.urlopen(..., $STR + $DATA, ...) + - pattern: | + $DATA = request.$W.get(...) + ... + $INTERM = $STR + $DATA + ... + urllib.request.urlopen(..., $INTERM, ...) + - pattern: $A = urllib.request.urlopen(..., request.$W.get(...), ...) + - pattern: return urllib.request.urlopen(..., request.$W.get(...), ...) + - pattern: urllib.request.urlopen(..., $S.format(..., request.$W(...), ...), ...) + - pattern: urllib.request.urlopen(..., $S % request.$W(...), ...) + - pattern: urllib.request.urlopen(..., f"...{request.$W(...)}...", ...) + - pattern: urllib.request.urlopen(..., request.$W(...), ...) + - pattern: | + $DATA = request.$W(...) + ... + urllib.request.urlopen(..., $DATA, ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = $DATA + ... + urllib.request.urlopen(..., $INTERM, ...) + - pattern: | + $DATA = request.$W(...) + ... + urllib.request.urlopen(..., $STR.format(..., $DATA, ...), ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = $STR.format(..., $DATA, ...) + ... + urllib.request.urlopen(..., $INTERM, ...) + - pattern: | + $DATA = request.$W(...) + ... + urllib.request.urlopen(..., $STR % $DATA, ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = $STR % $DATA + ... + urllib.request.urlopen(..., $INTERM, ...) + - pattern: | + $DATA = request.$W(...) + ... + urllib.request.urlopen(..., f"...{$DATA}...", ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = f"...{$DATA}..." + ... + urllib.request.urlopen(..., $INTERM, ...) + - pattern: | + $DATA = request.$W(...) + ... + urllib.request.urlopen(..., $STR + $DATA, ...) + - pattern: | + $DATA = request.$W(...) + ... + $INTERM = $STR + $DATA + ... + urllib.request.urlopen(..., $INTERM, ...) + - pattern: $A = urllib.request.urlopen(..., request.$W(...), ...) + - pattern: return urllib.request.urlopen(..., request.$W(...), ...) + - pattern: urllib.request.urlopen(..., $S.format(..., request.$W[...], ...), ...) + - pattern: urllib.request.urlopen(..., $S % request.$W[...], ...) + - pattern: urllib.request.urlopen(..., f"...{request.$W[...]}...", ...) + - pattern: urllib.request.urlopen(..., request.$W[...], ...) + - pattern: | + $DATA = request.$W[...] + ... + urllib.request.urlopen(..., $DATA, ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = $DATA + ... + urllib.request.urlopen(..., $INTERM, ...) + - pattern: | + $DATA = request.$W[...] + ... + urllib.request.urlopen(..., $STR.format(..., $DATA, ...), ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = $STR.format(..., $DATA, ...) + ... + urllib.request.urlopen(..., $INTERM, ...) + - pattern: | + $DATA = request.$W[...] + ... + urllib.request.urlopen(..., $STR % $DATA, ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = $STR % $DATA + ... + urllib.request.urlopen(..., $INTERM, ...) + - pattern: | + $DATA = request.$W[...] + ... + urllib.request.urlopen(..., f"...{$DATA}...", ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = f"...{$DATA}..." + ... + urllib.request.urlopen(..., $INTERM, ...) + - pattern: | + $DATA = request.$W[...] + ... + urllib.request.urlopen(..., $STR + $DATA, ...) + - pattern: | + $DATA = request.$W[...] + ... + $INTERM = $STR + $DATA + ... + urllib.request.urlopen(..., $INTERM, ...) + - pattern: $A = urllib.request.urlopen(..., request.$W[...], ...) + - pattern: return urllib.request.urlopen(..., request.$W[...], ...) + - pattern: urllib.request.urlopen(..., $S.format(..., request.$W, ...), ...) + - pattern: urllib.request.urlopen(..., $S % request.$W, ...) + - pattern: urllib.request.urlopen(..., f"...{request.$W}...", ...) + - pattern: urllib.request.urlopen(..., request.$W, ...) + - pattern: | + $DATA = request.$W + ... + urllib.request.urlopen(..., $DATA, ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = $DATA + ... + urllib.request.urlopen(..., $INTERM, ...) + - pattern: | + $DATA = request.$W + ... + urllib.request.urlopen(..., $STR.format(..., $DATA, ...), ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = $STR.format(..., $DATA, ...) + ... + urllib.request.urlopen(..., $INTERM, ...) + - pattern: | + $DATA = request.$W + ... + urllib.request.urlopen(..., $STR % $DATA, ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = $STR % $DATA + ... + urllib.request.urlopen(..., $INTERM, ...) + - pattern: | + $DATA = request.$W + ... + urllib.request.urlopen(..., f"...{$DATA}...", ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = f"...{$DATA}..." + ... + urllib.request.urlopen(..., $INTERM, ...) + - pattern: | + $DATA = request.$W + ... + urllib.request.urlopen(..., $STR + $DATA, ...) + - pattern: | + $DATA = request.$W + ... + $INTERM = $STR + $DATA + ... + urllib.request.urlopen(..., $INTERM, ...) + - pattern: $A = urllib.request.urlopen(..., request.$W, ...) + - pattern: return urllib.request.urlopen(..., request.$W, ...) +- id: python.django.security.injection.tainted-sql-string.tainted-sql-string + message: >- + Detected user input used to manually construct a SQL string. This is usually + bad practice because manual construction could accidentally result in a SQL + injection. An attacker could use a SQL injection to steal or modify contents + of the database. Instead, use a parameterized query which is available + by default in most database engines. Alternatively, consider using the Django + object-relational mappers (ORM) instead of raw SQL queries. + metadata: + cwe: + - 'CWE-915: Improperly Controlled Modification of Dynamically-Determined Object Attributes' + owasp: + - A08:2021 - Software and Data Integrity Failures + references: + - https://docs.djangoproject.com/en/3.0/topics/security/#sql-injection-protection + category: security + technology: + - django + subcategory: + - audit + impact: LOW + likelihood: MEDIUM + confidence: LOW + severity: ERROR + languages: + - python + mode: taint + pattern-sources: + - patterns: + - pattern: request.$ANYTHING + - pattern-not: request.build_absolute_uri + pattern-sinks: + - patterns: + - pattern-either: + - pattern: | + "$SQLSTR" + ... + - pattern: | + "$SQLSTR" % ... + - pattern: | + "$SQLSTR".format(...) + - pattern: | + f"$SQLSTR{...}..." + - metavariable-regex: + metavariable: $SQLSTR + regex: \s*(?i)(select|delete|insert|create|update|alter|drop)\b.* +- id: python.django.security.injection.tainted-url-host.tainted-url-host + languages: + - python + message: User data flows into the host portion of this manually-constructed URL. This could allow an + attacker to send data to their own server, potentially exposing sensitive data such as cookies or + authorization information sent with this request. They could also probe internal servers or other + resources that the server running this code can access. (This is called server-side request forgery, + or SSRF.) Do not allow arbitrary hosts. Instead, create an allowlist for approved hosts, or hardcode the + correct host. + metadata: + cwe: + - 'CWE-918: Server-Side Request Forgery (SSRF)' + owasp: + - A10:2021 - Server-Side Request Forgery (SSRF) + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet.html + category: security + technology: + - flask + license: Commons Clause License Condition v1.0[LGPL-2.1-only] + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + impact: MEDIUM + likelihood: LOW + confidence: LOW + mode: taint + pattern-sinks: + - patterns: + - pattern-either: + - patterns: + - pattern: '"$URLSTR" % ...' + - metavariable-pattern: + metavariable: $URLSTR + language: generic + patterns: + - pattern-either: + - pattern: $SCHEME://%s + - pattern: $SCHEME://%r + - patterns: + - pattern: '"$URLSTR".format(...)' + - metavariable-pattern: + metavariable: $URLSTR + language: generic + pattern: $SCHEME:// { ... } + - patterns: + - pattern: '"$URLSTR" + ...' + - metavariable-regex: + metavariable: $URLSTR + regex: .*://$ + - patterns: + - pattern: f"$URLSTR{...}..." + - metavariable-regex: + metavariable: $URLSTR + regex: .*://$ + - patterns: + - pattern-inside: | + $URL = "$URLSTR" + ... + - pattern: $URL += ... + - metavariable-regex: + metavariable: $URLSTR + regex: .*://$ + pattern-sources: + - patterns: + - pattern: request.$ANYTHING + - pattern-not: request.build_absolute_uri + severity: WARNING +- id: python.django.security.locals-as-template-context.locals-as-template-context + languages: + - python + message: >- + Using 'locals()' as a context to 'render(...)' is extremely dangerous. + This exposes Python functions to the template that were not meant to be exposed. + An attacker could use these functions to execute code that was not intended to run + and could compromise the application. (This is server-side template injection (SSTI)). + Do not use 'locals()'. Instead, specify each variable in a dictionary or + 'django.template.Context' object, like '{"var1": "hello"}' and use that instead. + metadata: + category: security + cwe: + - "CWE-96: Improper Neutralization of Directives in Statically Saved Code ('Static Code Injection')" + owasp: + - A03:2021 - Injection + references: + - https://docs.djangoproject.com/en/3.2/ref/settings/#templates + - https://docs.djangoproject.com/en/3.2/topics/templates/#django.template.backends.django.DjangoTemplates + - https://docs.djangoproject.com/en/3.2/ref/templates/api/#rendering-a-context + technology: + - django + subcategory: + - audit + likelihood: LOW + impact: HIGH + confidence: LOW + pattern-either: + - pattern: django.shortcuts.render(..., locals(...), ...) + - pattern: django.template.Template.render(..., locals(...), ...) + - patterns: + - pattern-inside: | + $CONTEXT = locals(...) + ... + - pattern-either: + - pattern: django.shortcuts.render(..., $CONTEXT, ...) + - pattern: django.template.Template.render(..., $CONTEXT, ...) + severity: ERROR +- id: python.django.security.nan-injection.nan-injection + message: Found user input going directly into typecast for bool(), float(), or complex(). This allows an + attacker to inject Python's not-a-number (NaN) into the typecast. This results in undefind behavior, + particularly when doing comparisons. Either cast to a different type, or add a guard checking for + all capitalizations of the string 'nan'. + languages: + - python + severity: ERROR + mode: taint + pattern-sources: + - patterns: + - pattern-inside: | + def $FUNC(request, ...): + ... + - pattern-either: + - pattern: request.$PROPERTY.get(...) + - pattern: request.$PROPERTY[...] + pattern-sinks: + - patterns: + - pattern-either: + - pattern: float(...) + - pattern: bool(...) + - pattern: complex(...) + - pattern-not-inside: | + if $COND: + ... + ... + pattern-sanitizers: + - pattern: $ANYTHING(...) + not_conflicting: true + metadata: + references: + - https://discuss.python.org/t/nan-breaks-min-max-and-sorting-functions-a-solution/2868 + - https://blog.bitdiscovery.com/2021/12/python-nan-injection/ + category: security + cwe: + - 'CWE-704: Incorrect Type Conversion or Cast' + technology: + - django + subcategory: + - vuln + impact: MEDIUM + likelihood: MEDIUM + confidence: MEDIUM +- id: python.django.security.passwords.password-empty-string.password-empty-string + message: >- + '$VAR' is the empty string and is being used to set the password on '$MODEL'. + If you meant to set an unusable password, set the password to None or call + 'set_unusable_password()'. + metadata: + cwe: + - 'CWE-521: Weak Password Requirements' + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://docs.djangoproject.com/en/3.0/ref/contrib/auth/#django.contrib.auth.models.User.set_password + category: security + technology: + - django + subcategory: + - vuln + likelihood: LOW + impact: MEDIUM + confidence: MEDIUM + patterns: + - pattern-either: + - pattern: | + $MODEL.set_password($EMPTY) + ... + $MODEL.save() + - pattern: | + $VAR = $EMPTY + ... + $MODEL.set_password($VAR) + ... + $MODEL.save() + - metavariable-regex: + metavariable: $EMPTY + regex: (\'\'|\"\") + languages: [python] + severity: ERROR +- id: python.django.security.passwords.use-none-for-password-default.use-none-for-password-default + message: >- + '$VAR' is using the empty string as its default and is being used to set + the password on '$MODEL'. If you meant to set an unusable password, set + the default value to 'None' or call 'set_unusable_password()'. + metadata: + cwe: + - 'CWE-521: Weak Password Requirements' + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://docs.djangoproject.com/en/3.0/ref/contrib/auth/#django.contrib.auth.models.User.set_password + category: security + technology: + - django + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + languages: [python] + severity: ERROR + patterns: + - pattern-either: + - pattern: | + $VAR = request.$W.get($X, $EMPTY) + ... + $MODEL.set_password($VAR) + ... + $MODEL.save(...) + - pattern: | + def $F(..., $VAR=$EMPTY, ...): + ... + $MODEL.set_password($VAR) + - metavariable-pattern: + metavariable: $EMPTY + pattern: '""' + - focus-metavariable: $EMPTY + fix: | + None +- id: python.docker.security.audit.docker-arbitrary-container-run.docker-arbitrary-container-run + patterns: + - pattern-either: + - pattern-inside: | + $CLIENT = docker.from_env() + ... + - pattern-inside: | + $CLIENT = docker.DockerClient(...) + ... + - pattern-either: + - pattern: | + $CLIENT.containers.run(...) + - pattern: | + $CLIENT.containers.create(...) + - pattern-not: | + $CLIENT.containers.run("...",...) + - pattern-not: | + $CLIENT.containers.create("...",...) + message: >- + If unverified user data can reach the `run` or `create` method it can result in running arbitrary + container. + languages: + - python + severity: WARNING + metadata: + cwe: + - 'CWE-250: Execution with Unnecessary Privileges' + category: security + technology: + - docker + references: + - https://cwe.mitre.org/data/definitions/250.html + subcategory: + - audit + likelihood: LOW + impact: HIGH + confidence: LOW +- id: python.fastapi.security.wildcard-cors.wildcard-cors + languages: + - python + message: CORS policy allows any origin (using wildcard '*'). This is insecure + and should be avoided. + mode: taint + pattern-sources: + - pattern: '[..., "*", ...]' + pattern-sinks: + - patterns: + - pattern: | + $APP.add_middleware( + CORSMiddleware, + allow_origins=$ORIGIN, + ...); + - focus-metavariable: $ORIGIN + severity: WARNING + metadata: + cwe: + - "CWE-942: Permissive Cross-domain Policy with Untrusted Domains" + owasp: + - A05:2021 - Security Misconfiguration + category: security + technology: + - python + - fastapi + references: + - https://owasp.org/Top10/A05_2021-Security_Misconfiguration + - https://cwe.mitre.org/data/definitions/942.html + likelihood: HIGH + impact: LOW + confidence: MEDIUM + vulnerability_class: + - Configuration + subcategory: + - vuln +- id: python.flask.best-practice.get-class-method-with-side-effects.flask-class-method-get-side-effects + patterns: + - pattern-either: + - pattern: | + def get(self,...): + ... + $METHOD(...) + - pattern: | + def get(self,...): + ... + $VAR = $METHOD(...) + - metavariable-regex: + metavariable: $METHOD + regex: (?i)(create|update|delete).* + message: >- + Flask class method GET with side effects + severity: WARNING + languages: [python] + metadata: + category: best-practice + technology: + - flask +- id: python.flask.best-practice.use-jsonify.use-jsonify + patterns: + - pattern: $JSONDUMPS + - pattern-either: + - pattern-inside: | + return json.dumps($...VAR) + - pattern-inside: | + $DATA = json.dumps($...VAR) + ... + return $DATA + - pattern-inside: | + @app.route(...) + def $X(): + ... + - metavariable-pattern: + metavariable: $JSONDUMPS + pattern: json.dumps($...VAR) + - focus-metavariable: $JSONDUMPS + fix: | + flask.jsonify($...VAR) + message: >- + flask.jsonify() is a Flask helper method which handles the correct + settings for returning JSON from Flask routes + languages: [python] + severity: ERROR + metadata: + category: best-practice + technology: + - flask + references: + - https://flask.palletsprojects.com/en/2.2.x/api/#flask.json.jsonify +- id: python.flask.caching.query-string.flask-cache-query-string + patterns: + - pattern-either: + - pattern: | + @app.route("...") + @cache.cached(...) + def $HANDLER(...): + ... + request.args.get(...) + - pattern: | + @app.route("...", methods=[..., "POST", ...]) + @cache.cached(...) + def $HANDLER(...): + ... + - pattern: | + @app.route("...", methods=[..., "PUT", ...]) + @cache.cached(...) + def $HANDLER(...): + ... + - pattern: | + @app.route("...", methods=[..., "DELETE", ...]) + @cache.cached(...) + def $HANDLER(...): + ... + - pattern: | + @app.route("...", methods=[..., "PATCH", ...]) + @cache.cached(...) + def $HANDLER(...): + ... + - pattern-not: | + @app.route("...") + @cache.cached(..., query_string=True) + def $HANDLER(...): + ... + request.args.get(...) + message: >- + Flask-caching doesn't cache query strings by default. You have to use `query_string=True`. Also you shouldn't cache verbs that can mutate state. + severity: WARNING + languages: + - python + metadata: + category: caching + technology: + - flask +- id: python.flask.correctness.access-request-in-wrong-handler.avoid-accessing-request-in-wrong-handler + patterns: + - pattern-inside: | + @app.route(..., method="GET") + def $X(...): + ... + - pattern-either: + - pattern: | + $Y = flask.request.json + - pattern: | + $Y = flask.request.form + - pattern: | + $Y = flask.request.data + message: Accessing request object inside a route handle for HTTP GET command will throw due to missing request body. + languages: [python] + severity: WARNING + metadata: + category: correctness + technology: + - flask +- id: python.flask.correctness.same-handler-name.flask-duplicate-handler-name + pattern: | + @app.route("...", ...) + def $R(...): + ... + ... + @app.route("...", ...) + def $R(...): + ... + message: + Looks like `$R` is a flask function handler that registered to two different routes. This will cause a runtime + error + languages: [python] + severity: WARNING + metadata: + category: correctness + technology: + - flask +- id: python.flask.maintainability.deprecated.deprecated-apis.flask-deprecated-apis + message: deprecated Flask API + languages: [python] + severity: WARNING + pattern-either: + - pattern: | + $F = Flask(...) + ... + $F.open_session(...) + - pattern: | + $F = Flask(...) + ... + $F.save_session(...) + - pattern: | + $F = Flask(...) + ... + $F.make_null_session(...) + - pattern: | + $F = Flask(...) + ... + $F.init_jinja_globals(...) + - pattern: | + $F = Flask(...) + ... + $F.request_globals_class(...) + - pattern: | + $F = Flask(...) + ... + $F.static_path(...) + - pattern: app.open_session(...) + - pattern: app.save_session(...) + - pattern: app.make_null_session(...) + - pattern: app.init_jinja_globals(...) + - pattern: app.request_globals_class(...) + - pattern: app.static_path(...) + - pattern: app.config.from_json(...) + - pattern: flask.json_available + - pattern: flask.request.module + - pattern: flask.testing.make_test_environ_builder(...) + metadata: + category: maintainability + technology: + - flask +- id: python.flask.security.audit.app-run-param-config.avoid_app_run_with_bad_host + message: Running flask app with host 0.0.0.0 could expose the server publicly. + metadata: + cwe: + - 'CWE-668: Exposure of Resource to Wrong Sphere' + owasp: + - A01:2021 - Broken Access Control + category: security + technology: + - flask + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - vuln + likelihood: HIGH + impact: MEDIUM + confidence: HIGH + languages: [python] + severity: WARNING + pattern-either: + - pattern: app.run(..., host="0.0.0.0", ...) + - pattern: app.run(..., "0.0.0.0", ...) +- id: python.flask.security.audit.app-run-security-config.avoid_using_app_run_directly + patterns: + - pattern-not-inside: | + if __name__ == '__main__': + ... + - pattern-not-inside: | + def $X(...): + ... + - pattern: app.run(...) + message: top-level app.run(...) is ignored by flask. Consider putting app.run(...) behind a guard, like + inside a function + metadata: + cwe: + - 'CWE-668: Exposure of Resource to Wrong Sphere' + owasp: + - A01:2021 - Broken Access Control + category: security + technology: + - flask + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - vuln + likelihood: LOW + impact: MEDIUM + confidence: MEDIUM + languages: [python] + severity: WARNING +- id: python.flask.security.audit.debug-enabled.debug-enabled + patterns: + - pattern-inside: | + import flask + ... + - pattern: $APP.run(..., debug=True, ...) + message: >- + Detected Flask app with debug=True. Do not deploy to production with this flag enabled + as it will leak sensitive information. Instead, consider using Flask configuration + variables or setting 'debug' using system environment variables. + metadata: + cwe: + - 'CWE-489: Active Debug Code' + owasp: 'A06:2017 - Security Misconfiguration' + references: + - https://labs.detectify.com/2015/10/02/how-patreon-got-hacked-publicly-exposed-werkzeug-debugger/ + category: security + technology: + - flask + subcategory: + - vuln + likelihood: HIGH + impact: MEDIUM + confidence: HIGH + severity: WARNING + languages: + - python +- id: python.flask.security.audit.directly-returned-format-string.directly-returned-format-string + message: >- + Detected Flask route directly returning a formatted string. This + is subject to cross-site scripting if user input can reach the string. + Consider using the template engine instead and rendering pages with + 'render_template()'. + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + category: security + technology: + - flask + references: + - https://owasp.org/Top10/A03_2021-Injection + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: HIGH + impact: MEDIUM + confidence: MEDIUM + languages: + - python + severity: WARNING + mode: taint + pattern-sources: + - pattern-either: + - patterns: + - pattern-inside: | + @$APP.route(...) + def $FUNC(..., $PARAM, ...): + ... + - pattern: $PARAM + - pattern: | + request.$FUNC.get(...) + - pattern: | + request.$FUNC(...) + - pattern: request.$FUNC[...] + pattern-sinks: + - patterns: + - pattern-not-inside: return "..." + - pattern-either: + - pattern: return "...".format(...) + - pattern: return "..." % ... + - pattern: return "..." + ... + - pattern: return ... + "..." + - pattern: return f"...{...}..." + - patterns: + - pattern: return $X + - pattern-either: + - pattern-inside: | + $X = "...".format(...) + ... + - pattern-inside: | + $X = "..." % ... + ... + - pattern-inside: | + $X = "..." + ... + ... + - pattern-inside: | + $X = ... + "..." + ... + - pattern-inside: | + $X = f"...{...}..." + ... + - pattern-not-inside: | + $X = "..." + ... +- id: python.flask.security.audit.hardcoded-config.avoid_hardcoded_config_testing + message: Hardcoded variable `TESTING` detected. Use environment variables or config files instead + severity: WARNING + metadata: + likelihood: LOW + impact: LOW + confidence: LOW + category: security + cwe: + - 'CWE-489: Active Debug Code' + owasp: + - A05:2021 - Security Misconfiguration + references: + - https://bento.dev/checks/flask/avoid-hardcoded-config/ + - https://flask.palletsprojects.com/en/1.1.x/config/?highlight=configuration#builtin-configuration-values + - https://flask.palletsprojects.com/en/1.1.x/config/?highlight=configuration#environment-and-debug-features + subcategory: + - audit + technology: + - flask + languages: [python] + pattern-either: + - pattern: $M.config['TESTING'] = True + - pattern: $M.config['TESTING'] = False + - pattern: $M.update(TESTING=True, ...) + - pattern: $M.update(TESTING=False, ...) +- id: python.flask.security.audit.hardcoded-config.avoid_hardcoded_config_secret_key + message: Hardcoded variable `SECRET_KEY` detected. Use environment variables or config files instead + severity: ERROR + metadata: + likelihood: LOW + impact: LOW + confidence: LOW + category: security + cwe: + - 'CWE-489: Active Debug Code' + owasp: + - A05:2021 - Security Misconfiguration + references: + - https://bento.dev/checks/flask/avoid-hardcoded-config/ + - https://flask.palletsprojects.com/en/1.1.x/config/?highlight=configuration#builtin-configuration-values + - https://flask.palletsprojects.com/en/1.1.x/config/?highlight=configuration#environment-and-debug-features + subcategory: + - audit + technology: + - flask + languages: [python] + pattern-either: + - pattern: $M.update(SECRET_KEY="=~/.*/") + - pattern: $M.config['SECRET_KEY'] = "=~/.*/" +- id: python.flask.security.audit.hardcoded-config.avoid_hardcoded_config_env + message: Hardcoded variable `ENV` detected. Set this by using FLASK_ENV environment variable + severity: WARNING + metadata: + likelihood: LOW + impact: LOW + confidence: LOW + category: security + cwe: + - 'CWE-489: Active Debug Code' + owasp: + - A05:2021 - Security Misconfiguration + references: + - https://bento.dev/checks/flask/avoid-hardcoded-config/ + - https://flask.palletsprojects.com/en/1.1.x/config/?highlight=configuration#builtin-configuration-values + - https://flask.palletsprojects.com/en/1.1.x/config/?highlight=configuration#environment-and-debug-features + subcategory: + - audit + technology: + - flask + languages: [python] + pattern-either: + - pattern: $M.update(ENV="=~/^development|production$/") + - pattern: $M.config['ENV'] = "=~/^development|production$/" +- id: python.flask.security.audit.hardcoded-config.avoid_hardcoded_config_debug + message: Hardcoded variable `DEBUG` detected. Set this by using FLASK_DEBUG environment variable + severity: WARNING + metadata: + likelihood: LOW + impact: LOW + confidence: LOW + category: security + cwe: + - 'CWE-489: Active Debug Code' + owasp: + - A05:2021 - Security Misconfiguration + references: + - https://bento.dev/checks/flask/avoid-hardcoded-config/ + - https://flask.palletsprojects.com/en/1.1.x/config/?highlight=configuration#builtin-configuration-values + - https://flask.palletsprojects.com/en/1.1.x/config/?highlight=configuration#environment-and-debug-features + subcategory: + - audit + technology: + - flask + languages: [python] + pattern-either: + - pattern: $M.update(DEBUG=True) + - pattern: $M.update(DEBUG=False) + - pattern: $M.config['DEBUG'] = True + - pattern: $M.config['DEBUG'] = False +- id: python.flask.security.audit.host-header-injection-python.host-header-injection-python + message: >- + The `flask.request.host` is used to construct an HTTP request. + This can lead to host header injection issues. Vulnerabilities + that generally occur due to this issue are authentication bypasses, + password reset issues, Server-Side-Request-Forgery (SSRF), and many more. + It is recommended to validate the URL before passing it to a + request library, or using application logic such as authentication + or password resets. + patterns: + - pattern-either: + - pattern: | + $X = <... "=~/.*http[s]*:///" + flask.request.host ...>; + - pattern: | + $X = <... "=~/.*http[s]*:///" + flask.request["host"] ...>; + - pattern: | + $Z = flask.request.host; + ... + $X = <... "=~/.*http[s]*:///" + $Z ...>; + - pattern: | + $Z = flask.request["host"]; + ... + $X = <... "=~/.*http[s]*:///" + $Z ...>; + - pattern-inside: | + @$APP.route($ROUTE, ...) + def $FUNC(): + ... + languages: + - python + severity: INFO + metadata: + cwe: + - 'CWE-20: Improper Input Validation' + category: security + references: + - https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/07-Input_Validation_Testing/17-Testing_for_Host_Header_Injection + - https://cheatsheetseries.owasp.org/cheatsheets/Input_Validation_Cheat_Sheet.html + technology: + - flask + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + license: Commons Clause License Condition v1.0[LGPL-2.1-only] +- id: python.flask.security.audit.render-template-string.render-template-string + pattern: flask.render_template_string(...) + metadata: + cwe: + - "CWE-96: Improper Neutralization of Directives in Statically Saved Code ('Static Code Injection')" + owasp: + - A03:2021 - Injection + references: + - https://nvisium.com/blog/2016/03/09/exploring-ssti-in-flask-jinja2.html + category: security + technology: + - flask + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + message: Found a template created with string formatting. This is susceptible to server-side template + injection and cross-site scripting attacks. + languages: [python] + severity: WARNING +- id: python.flask.security.audit.secure-set-cookie.secure-set-cookie + patterns: + - pattern-either: + - pattern-inside: | + $RESP = flask.make_response(...) + ... + - pattern-inside: | + $RESP = flask.Response(...) + ... + - pattern-not: $RESP.set_cookie(..., secure=$A, httponly=$B, samesite=$C, ...) + - pattern-not: $RESP.set_cookie(..., **$A) + - pattern: $RESP.set_cookie(...) + message: >- + Found a Flask cookie with insecurely configured properties. + By default the secure, httponly and samesite ar configured insecurely. + cookies should be handled securely by setting `secure=True`, `httponly=True`, and + `samesite='Lax'` in response.set_cookie(...). If these parameters are not properly + set, your cookies are not properly protected and are at risk of being stolen by + an attacker. Include the `secure=True`, `httponly=True`, `samesite='Lax'` arguments + or set these to be true in the Flask configuration. + metadata: + cwe: + - "CWE-614: Sensitive Cookie in HTTPS Session Without 'Secure' Attribute" + owasp: + - A05:2021 - Security Misconfiguration + references: + - https://flask.palletsprojects.com/en/3.0.x/api/#flask.Response.set_cookie + - https://flask.palletsprojects.com/en/3.0.x/security/#set-cookie-options + category: security + technology: + - python + - flask + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + functional-categories: + - web::search::cookie-config::flask + languages: [python] + severity: WARNING +- id: python.flask.security.audit.wtf-csrf-disabled.flask-wtf-csrf-disabled + message: >- + Setting 'WTF_CSRF_ENABLED' to 'False' explicitly disables CSRF protection. + options: + symbolic_propagation: true + metadata: + cwe: + - 'CWE-352: Cross-Site Request Forgery (CSRF)' + owasp: + - A01:2021 - Broken Access Control + references: + - https://flask-wtf.readthedocs.io/en/1.2.x/csrf/ + category: security + technology: + - flask + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + functional-categories: + - web::search::csrf-config::flask + - web::search::csrf-config::flask-wtf + severity: WARNING + languages: + - python + patterns: + - pattern-either: + - patterns: + - pattern-either: + - pattern: $APP.config["WTF_CSRF_ENABLED"] = $FALSE + - pattern: $APP.config.WTF_CSRF_ENABLED = $FALSE + - patterns: + - pattern: | + $APP.config.$UPDATE( + ..., + WTF_CSRF_ENABLED = $FALSE, + ... + ) + - pattern-not-inside: | + $APP.config.$UPDATE( + ..., + TESTING=True, + ... + ) + - pattern-not-inside: | + $APP.config.$UPDATE( + ..., + DEBUG=True, + ... + ) + - metavariable-regex: + metavariable: $UPDATE + regex: ^(update|from_mapping)$ + - pattern: | + $OBJ = $CLASS() + ... + $OBJ.WTF_CSRF_ENABLED = $FALSE + ... + $APP.config.from_object($OBJ, ...) + - pattern: | + WTF_CSRF_ENABLED = $FALSE + ... + $APP.config.from_object(__name__) + - metavariable-regex: + metavariable: $FALSE + regex: ^(False)$ + - focus-metavariable: $FALSE + fix: 'True' + + +- id: python.flask.security.audit.xss.make-response-with-unknown-content.make-response-with-unknown-content + patterns: + - pattern: flask.make_response(...) + - pattern-not-inside: flask.make_response() + - pattern-not-inside: flask.make_response("...", ...) + - pattern-not-inside: 'flask.make_response({"...": "..."}, ...)' + - pattern-not-inside: flask.make_response(flask.redirect(...), ...) + - pattern-not-inside: flask.make_response(flask.render_template(...), ...) + - pattern-not-inside: flask.make_response(flask.jsonify(...), ...) + - pattern-not-inside: flask.make_response(json.dumps(...), ...) + - pattern-not-inside: | + $X = flask.render_template(...) + ... + flask.make_response($X, ...) + - pattern-not-inside: | + $X = flask.jsonify(...) + ... + flask.make_response($X, ...) + - pattern-not-inside: | + $X = json.dumps(...) + ... + flask.make_response($X, ...) + message: >- + Be careful with `flask.make_response()`. If this response is rendered onto a webpage, + this could create a cross-site scripting (XSS) vulnerability. `flask.make_response()` + will not autoescape HTML. If you are rendering HTML, write your HTML in a template + file and + use `flask.render_template()` which will take care of escaping. + If you are returning data from an API, consider using `flask.jsonify()`. + severity: WARNING + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + references: + - https://github.com/python-security/pyt//blob/093a077bcf12d1f58ddeb2d73ddc096623985fb0/examples/vulnerable_code/XSS_assign_to_other_var.py#L11 + - https://flask.palletsprojects.com/en/1.1.x/api/#flask.Flask.make_response + - https://flask.palletsprojects.com/en/1.1.x/api/#response-objects + category: security + technology: + - flask + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + languages: + - python +- id: python.flask.security.dangerous-template-string.dangerous-template-string + message: >- + Found a template created with string formatting. + This is susceptible to server-side template injection + and cross-site scripting attacks. + metadata: + cwe: + - "CWE-96: Improper Neutralization of Directives in Statically Saved Code ('Static Code Injection')" + owasp: + - A03:2021 - Injection + references: + - https://nvisium.com/blog/2016/03/09/exploring-ssti-in-flask-jinja2.html + - https://pequalsnp-team.github.io/cheatsheet/flask-jinja2-ssti + category: security + technology: + - flask + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + languages: [python] + severity: ERROR + pattern-either: + - pattern: | + $V = "...".format(...) + ... + flask.render_template_string($V, ...) + - pattern: | + $V = "...".format(...) + ... + return flask.render_template_string($V, ...), $MORE + - pattern: | + $V = "..." % $S + ... + flask.render_template_string($V, ...) + - pattern: | + $V = "..." % $S + ... + return flask.render_template_string($V, ...), $MORE + - pattern: | + $V = "..." + ... + $V += $O + ... + flask.render_template_string($V, ...) + - pattern: | + $V = "..." + ... + $V += $O + ... + return flask.render_template_string($V, ...), $MORE + - pattern: | + $V = f"...{$X}..." + ... + flask.render_template_string($V, ...) + - pattern: | + $V = f"...{$X}..." + ... + return flask.render_template_string($V, ...), $CODE +- id: python.flask.security.flask-api-method-string-format.flask-api-method-string-format + patterns: + - pattern-either: + - pattern: | + def $METHOD(...,$ARG,...): + ... + $STRING = "...".format(...,$ARG,...) + ... + ... = requests.$REQMETHOD($STRING,...) + - pattern: | + def $METHOD(...,$ARG,...): + ... + ... = requests.$REQMETHOD("...".format(...,$ARG,...),...) + - pattern-inside: | + class $CLASS(...): + method_decorators = ... + ... + message: >- + Method $METHOD in API controller $CLASS provides user arg $ARG to requests method $REQMETHOD + severity: ERROR + languages: + - python + metadata: + cwe: + - 'CWE-134: Use of Externally-Controlled Format String' + category: security + technology: + - flask + references: + - https://cwe.mitre.org/data/definitions/134.html + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW +- id: python.flask.security.hashids-with-flask-secret.hashids-with-flask-secret + languages: + - python + message: >- + The Flask secret key is used as salt in HashIDs. The HashID mechanism is not secure. + By observing sufficient HashIDs, the salt used to construct them can be recovered. + This means the Flask secret key can be obtained by attackers, through the HashIDs. + metadata: + category: security + subcategory: + - vuln + cwe: + - "CWE-327: Use of a Broken or Risky Cryptographic Algorithm" + owasp: + - A02:2021 – Cryptographic Failures + references: + - https://flask.palletsprojects.com/en/2.2.x/config/#SECRET_KEY + - http://carnage.github.io/2015/08/cryptanalysis-of-hashids + technology: + - flask + likelihood: LOW + impact: HIGH + confidence: HIGH + pattern-either: + - pattern: hashids.Hashids(..., salt=flask.current_app.config['SECRET_KEY'], ...) + - pattern: hashids.Hashids(flask.current_app.config['SECRET_KEY'], ...) + - patterns: + - pattern-inside: | + $APP = flask.Flask(...) + ... + - pattern-either: + - pattern: hashids.Hashids(..., salt=$APP.config['SECRET_KEY'], ...) + - pattern: hashids.Hashids($APP.config['SECRET_KEY'], ...) + severity: ERROR +- id: python.flask.security.injection.csv-writer-injection.csv-writer-injection + languages: + - python + message: Detected user input into a generated CSV file using the built-in `csv` module. If user data + is used to generate the data in this file, it is possible that an attacker could inject a formula + when the CSV is imported into a spreadsheet application that runs an attacker script, which could + steal data from the importing user or, at worst, install malware on the user's computer. `defusedcsv` + is a drop-in replacement with the same API that will attempt to mitigate formula injection attempts. + You can use `defusedcsv` instead of `csv` to safely generate CSVs. + metadata: + category: security + confidence: MEDIUM + cwe: + - 'CWE-1236: Improper Neutralization of Formula Elements in a CSV File' + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + references: + - https://github.com/raphaelm/defusedcsv + - https://owasp.org/www-community/attacks/CSV_Injection + - https://web.archive.org/web/20220516052229/https://www.contextis.com/us/blog/comma-separated-vulnerabilities + technology: + - python + - flask + subcategory: + - vuln + impact: MEDIUM + likelihood: MEDIUM + mode: taint + pattern-sinks: + - patterns: + - pattern-inside: | + $WRITER = csv.writer(...) + + ... + + $WRITER.$WRITE(...) + - pattern: $WRITER.$WRITE(...) + - metavariable-regex: + metavariable: $WRITE + regex: ^(writerow|writerows|writeheader)$ + pattern-sources: + - patterns: + - pattern-either: + - patterns: + - pattern-either: + - pattern: flask.request.form.get(...) + - pattern: flask.request.form[...] + - pattern: flask.request.args.get(...) + - pattern: flask.request.args[...] + - pattern: flask.request.values.get(...) + - pattern: flask.request.values[...] + - pattern: flask.request.cookies.get(...) + - pattern: flask.request.cookies[...] + - pattern: flask.request.stream + - pattern: flask.request.headers.get(...) + - pattern: flask.request.headers[...] + - pattern: flask.request.data + - pattern: flask.request.full_path + - pattern: flask.request.url + - pattern: flask.request.json + - pattern: flask.request.get_json() + - pattern: flask.request.view_args.get(...) + - pattern: flask.request.view_args[...] + - patterns: + - pattern-inside: | + @$APP.route($ROUTE, ...) + def $FUNC(..., $ROUTEVAR, ...): + ... + - focus-metavariable: $ROUTEVAR + severity: ERROR +- id: python.flask.security.injection.nan-injection.nan-injection + message: Found user input going directly into typecast for bool(), float(), or complex(). This allows an + attacker to inject Python's not-a-number (NaN) into the typecast. This results in undefind behavior, + particularly when doing comparisons. Either cast to a different type, or add a guard checking for + all capitalizations of the string 'nan'. + languages: + - python + severity: ERROR + mode: taint + pattern-sources: + - pattern-either: + - pattern: flask.request.$SOMETHING.get(...) + - pattern: flask.request.$SOMETHING[...] + - patterns: + - pattern-inside: | + @$APP.route(...) + def $FUNC(..., $ROUTEVAR, ...): + ... + - pattern: $ROUTEVAR + pattern-sinks: + - pattern-either: + - pattern: float(...) + - pattern: bool(...) + - pattern: complex(...) + pattern-sanitizers: + - not_conflicting: true + pattern: $ANYTHING(...) + metadata: + references: + - https://discuss.python.org/t/nan-breaks-min-max-and-sorting-functions-a-solution/2868 + - https://blog.bitdiscovery.com/2021/12/python-nan-injection/ + category: security + cwe: + - 'CWE-704: Incorrect Type Conversion or Cast' + technology: + - flask + subcategory: + - vuln + impact: MEDIUM + likelihood: MEDIUM + confidence: MEDIUM +- id: python.flask.security.injection.os-system-injection.os-system-injection + languages: + - python + severity: ERROR + message: >- + User data detected in os.system. This could be vulnerable to a command injection and should be avoided. + If this + must be done, use the 'subprocess' module instead and pass the arguments as a list. + metadata: + cwe: + - "CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')" + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + references: + - https://owasp.org/www-community/attacks/Command_Injection + category: security + technology: + - flask + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: MEDIUM + impact: HIGH + confidence: MEDIUM + pattern-either: + - patterns: + - pattern: os.system(...) + - pattern-either: + - pattern-inside: | + @$APP.route($ROUTE, ...) + def $FUNC(..., $ROUTEVAR, ...): + ... + os.system(..., <... $ROUTEVAR ...>, ...) + - pattern-inside: | + @$APP.route($ROUTE, ...) + def $FUNC(..., $ROUTEVAR, ...): + ... + $INTERM = <... $ROUTEVAR ...> + ... + os.system(..., <... $INTERM ...>, ...) + - pattern: os.system(..., <... flask.request.$W.get(...) ...>, ...) + - pattern: os.system(..., <... flask.request.$W[...] ...>, ...) + - pattern: os.system(..., <... flask.request.$W(...) ...>, ...) + - pattern: os.system(..., <... flask.request.$W ...>, ...) + - patterns: + - pattern-inside: | + $INTERM = <... flask.request.$W.get(...) ...> + ... + os.system(<... $INTERM ...>) + - pattern: os.system(...) + - patterns: + - pattern-inside: | + $INTERM = <... flask.request.$W[...] ...> + ... + os.system(<... $INTERM ...>) + - pattern: os.system(...) + - patterns: + - pattern-inside: | + $INTERM = <... flask.request.$W(...) ...> + ... + os.system(<... $INTERM ...>) + - pattern: os.system(...) + - patterns: + - pattern-inside: | + $INTERM = <... flask.request.$W ...> + ... + os.system(<... $INTERM ...>) + - pattern: os.system(...) +- id: python.flask.security.injection.path-traversal-open.path-traversal-open + languages: + - python + severity: ERROR + message: >- + Found request data in a call to 'open'. Ensure the request data is validated or sanitized, otherwise + it could result + in path traversal attacks. + metadata: + cwe: + - "CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')" + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + references: + - https://owasp.org/www-community/attacks/Path_Traversal + category: security + technology: + - flask + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: MEDIUM + impact: HIGH + confidence: MEDIUM + pattern-either: + - patterns: + - pattern: open(...) + - pattern-either: + - pattern-inside: | + @$APP.route($ROUTE, ...) + def $FUNC(..., $ROUTEVAR, ...): + ... + open(..., <... $ROUTEVAR ...>, ...) + - pattern-inside: | + @$APP.route($ROUTE, ...) + def $FUNC(..., $ROUTEVAR, ...): + ... + with open(..., <... $ROUTEVAR ...>, ...) as $FD: + ... + - pattern-inside: | + @$APP.route($ROUTE, ...) + def $FUNC(..., $ROUTEVAR, ...): + ... + $INTERM = <... $ROUTEVAR ...> + ... + open(..., <... $INTERM ...>, ...) + - pattern: open(..., <... flask.request.$W.get(...) ...>, ...) + - pattern: open(..., <... flask.request.$W[...] ...>, ...) + - pattern: open(..., <... flask.request.$W(...) ...>, ...) + - pattern: open(..., <... flask.request.$W ...>, ...) + - patterns: + - pattern-inside: | + $INTERM = <... flask.request.$W.get(...) ...> + ... + open(<... $INTERM ...>, ...) + - pattern: open(...) + - patterns: + - pattern-inside: | + $INTERM = <... flask.request.$W[...] ...> + ... + open(<... $INTERM ...>, ...) + - pattern: open(...) + - patterns: + - pattern-inside: | + $INTERM = <... flask.request.$W(...) ...> + ... + open(<... $INTERM ...>, ...) + - pattern: open(...) + - patterns: + - pattern-inside: | + $INTERM = <... flask.request.$W ...> + ... + open(<... $INTERM ...>, ...) + - pattern: open(...) + - patterns: + - pattern-inside: | + $INTERM = <... flask.request.$W.get(...) ...> + ... + with open(<... $INTERM ...>, ...) as $F: + ... + - pattern: open(...) + - patterns: + - pattern-inside: | + $INTERM = <... flask.request.$W[...] ...> + ... + with open(<... $INTERM ...>, ...) as $F: + ... + - pattern: open(...) + - patterns: + - pattern-inside: | + $INTERM = <... flask.request.$W(...) ...> + ... + with open(<... $INTERM ...>, ...) as $F: + ... + - pattern: open(...) + - patterns: + - pattern-inside: | + $INTERM = <... flask.request.$W ...> + ... + with open(<... $INTERM ...>, ...) as $F: + ... + - pattern: open(...) +- id: python.flask.security.injection.raw-html-concat.raw-html-format + languages: + - python + severity: WARNING + message: >- + Detected user input flowing into a manually constructed HTML string. You may be accidentally bypassing + secure methods + of rendering HTML by manually constructing HTML and this could create a cross-site scripting vulnerability, + which could + let attackers steal sensitive user data. To be sure this is safe, check that the HTML is rendered + safely. Otherwise, use + templates (`flask.render_template`) which will safely render HTML instead. + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + category: security + technology: + - flask + references: + - https://flask.palletsprojects.com/en/2.0.x/security/#cross-site-scripting-xss + license: Commons Clause License Condition v1.0[LGPL-2.1-only] + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + mode: taint + pattern-sanitizers: + - pattern: jinja2.escape(...) + - pattern: flask.escape(...) + - pattern: flask.render_template("~=/.*\.html", ...) + pattern-sources: + - patterns: + - pattern-either: + - pattern: flask.request.$ANYTHING + - patterns: + - pattern-inside: | + @$APP.route(...) + def $FUNC(..., $ROUTEVAR, ...): + ... + - pattern: $ROUTEVAR + pattern-sinks: + - patterns: + - pattern-either: + - patterns: + - pattern-either: + - pattern: '"$HTMLSTR" % ...' + - pattern: '"$HTMLSTR".format(...)' + - pattern: '"$HTMLSTR" + ...' + - pattern: f"$HTMLSTR{...}..." + - patterns: + - pattern-inside: | + $HTML = "$HTMLSTR" + ... + - pattern-either: + - pattern: $HTML % ... + - pattern: $HTML.format(...) + - pattern: $HTML + ... + - metavariable-pattern: + metavariable: $HTMLSTR + language: generic + pattern: <$TAG ... +- id: python.flask.security.injection.ssrf-requests.ssrf-requests + languages: + - python + severity: ERROR + message: Data from request object is passed to a new server-side request. This could lead to a server-side + request forgery (SSRF). To mitigate, ensure that schemes and hosts are validated against an allowlist, + do not forward the response to the user, and ensure proper authentication and transport-layer security + in the proxied request. + metadata: + cwe: + - 'CWE-918: Server-Side Request Forgery (SSRF)' + owasp: + - A10:2021 - Server-Side Request Forgery (SSRF) + references: + - https://owasp.org/www-community/attacks/Server_Side_Request_Forgery + category: security + technology: + - flask + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: HIGH + confidence: MEDIUM + pattern-either: + - patterns: + # Written this way so that Semgrep only matches the requests call, + # not the whole function def + - pattern: requests.$FUNC(...) + - pattern-either: + - pattern-inside: | + @$APP.$ROUTE_METHOD($ROUTE, ...) + def $ROUTE_FUNC(..., $ROUTEVAR, ...): + ... + requests.$FUNC(..., <... $ROUTEVAR ...>, ...) + - pattern-inside: | + @$APP.$ROUTE_METHOD($ROUTE, ...) + def $ROUTE_FUNC(..., $ROUTEVAR, ...): + ... + $INTERM = <... $ROUTEVAR ...> + ... + requests.$FUNC(..., <... $INTERM ...>, ...) + - metavariable-regex: + metavariable: $ROUTE_METHOD + regex: ^(route|get|post|put|delete|patch)$ + - pattern: requests.$FUNC(..., <... flask.request.$W.get(...) ...>, ...) + - pattern: requests.$FUNC(..., <... flask.request.$W[...] ...>, ...) + - pattern: requests.$FUNC(..., <... flask.request.$W(...) ...>, ...) + - pattern: requests.$FUNC(..., <... flask.request.$W ...>, ...) + - patterns: + - pattern-inside: | + $INTERM = <... flask.request.$W.get(...) ...> + ... + requests.$FUNC(<... $INTERM ...>, ...) + - pattern: requests.$FUNC(...) + - patterns: + - pattern-inside: | + $INTERM = <... flask.request.$W[...] ...> + ... + requests.$FUNC(<... $INTERM ...>, ...) + - pattern: requests.$FUNC(...) + - patterns: + - pattern-inside: | + $INTERM = <... flask.request.$W(...) ...> + ... + requests.$FUNC(<... $INTERM ...>, ...) + - pattern: requests.$FUNC(...) + - patterns: + - pattern-inside: | + $INTERM = <... flask.request.$W ...> + ... + requests.$FUNC(<... $INTERM ...>, ...) + - pattern: requests.$FUNC(...) +- id: python.flask.security.injection.subprocess-injection.subprocess-injection + languages: [python] + mode: taint + options: + symbolic_propagation: true + pattern-sources: + - pattern-either: + - patterns: + - pattern-either: + - pattern: flask.request.form.get(...) + - pattern: flask.request.form[...] + - pattern: flask.request.args.get(...) + - pattern: flask.request.args[...] + - pattern: flask.request.values.get(...) + - pattern: flask.request.values[...] + - pattern: flask.request.cookies.get(...) + - pattern: flask.request.cookies[...] + - pattern: flask.request.stream + - pattern: flask.request.headers.get(...) + - pattern: flask.request.headers[...] + - pattern: flask.request.data + - pattern: flask.request.full_path + - pattern: flask.request.url + - pattern: flask.request.json + - pattern: flask.request.get_json() + - pattern: flask.request.view_args.get(...) + - pattern: flask.request.view_args[...] + - patterns: + - pattern-inside: | + @$APP.route($ROUTE, ...) + def $FUNC(..., $ROUTEVAR, ...): + ... + - focus-metavariable: $ROUTEVAR + pattern-sinks: + - patterns: + - pattern-either: + - patterns: + - pattern: subprocess.$FUNC(...) + - pattern-not: subprocess.$FUNC("...", ...) + - pattern-not: subprocess.$FUNC(["...", ...], ...) + - pattern-not-inside: | + $CMD = ["...", ...] + ... + subprocess.$FUNC($CMD, ...) + - patterns: + - pattern: subprocess.$FUNC(["$SHELL", "-c", ...], ...) + - metavariable-regex: + metavariable: $SHELL + regex: ^(sh|bash|ksh|csh|tcsh|zsh)$ + - patterns: + - pattern: subprocess.$FUNC(["$INTERPRETER", ...], ...) + - metavariable-regex: + metavariable: $INTERPRETER + regex: ^(python|python\d)$ + pattern-sanitizers: + - patterns: + - pattern: $DICT[$KEY] + - focus-metavariable: $KEY + severity: ERROR + message: >- + Detected user input entering a `subprocess` call unsafely. This could + result in a command injection vulnerability. An attacker could use this + vulnerability to execute arbitrary commands on the host, which allows + them to download malware, scan sensitive data, or run any command they + wish on the server. Do not let users choose the command to run. In general, + prefer to use Python API versions of system commands. If you must use subprocess, + use a dictionary to allowlist a set of commands. + metadata: + category: security + technology: + - flask + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + cwe: + - "CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')" + references: + - https://semgrep.dev/docs/cheat-sheets/python-command-injection/ + confidence: HIGH + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: HIGH + impact: MEDIUM +- id: python.flask.security.injection.tainted-sql-string.tainted-sql-string + message: >- + Detected user input used to manually construct a SQL string. This is usually + bad practice because manual construction could accidentally result in a SQL + injection. An attacker could use a SQL injection to steal or modify contents + of the database. Instead, use a parameterized query which is available + by default in most database engines. Alternatively, consider using an + object-relational mapper (ORM) such as SQLAlchemy which will protect your queries. + metadata: + cwe: + - 'CWE-704: Incorrect Type Conversion or Cast' + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + references: + - https://docs.sqlalchemy.org/en/14/core/tutorial.html#using-textual-sql + - https://www.tutorialspoint.com/sqlalchemy/sqlalchemy_quick_guide.htm + - https://docs.sqlalchemy.org/en/14/core/tutorial.html#using-more-specific-text-with-table-expression-literal-column-and-expression-column + category: security + technology: + - sqlalchemy + - flask + subcategory: + - vuln + impact: MEDIUM + likelihood: MEDIUM + confidence: MEDIUM + severity: ERROR + languages: + - python + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - pattern: flask.request.$ANYTHING + - patterns: + - pattern-inside: | + @$APP.route(...) + def $FUNC(..., $ROUTEVAR, ...): + ... + - pattern: $ROUTEVAR + pattern-sinks: + - patterns: + - pattern-either: + - pattern: | + "$SQLSTR" + ... + - pattern: | + "$SQLSTR" % ... + - pattern: | + "$SQLSTR".format(...) + - pattern: | + f"$SQLSTR{...}..." + - metavariable-regex: + metavariable: $SQLSTR + regex: \s*(?i)(select|delete|insert|create|update|alter|drop)\b.* +- id: python.flask.security.injection.tainted-url-host.tainted-url-host + languages: + - python + message: >- + User data flows into the host portion of this manually-constructed URL. + This could allow an attacker to send data to their own server, potentially + exposing sensitive data such as cookies or authorization information sent + with this request. They could also probe internal servers or other + resources that the server running this code can access. (This is called + server-side request forgery, or SSRF.) Do not allow arbitrary hosts. + Instead, create an allowlist for approved hosts, or hardcode the correct host. + metadata: + cwe: + - 'CWE-918: Server-Side Request Forgery (SSRF)' + owasp: + - A10:2021 - Server-Side Request Forgery (SSRF) + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet.html + category: security + technology: + - flask + license: Commons Clause License Condition v1.0[LGPL-2.1-only] + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + impact: MEDIUM + likelihood: MEDIUM + confidence: MEDIUM + mode: taint + pattern-sinks: + - patterns: + - pattern-either: + - patterns: + - pattern: '"$URLSTR" % ...' + - metavariable-pattern: + metavariable: $URLSTR + language: generic + patterns: + - pattern-either: + - pattern: $SCHEME://%s + - pattern: $SCHEME://%r + - patterns: + - pattern: '"$URLSTR".format(...)' + - metavariable-pattern: + metavariable: $URLSTR + language: generic + pattern: $SCHEME:// { ... } + - patterns: + - pattern: '"$URLSTR" + ...' + - metavariable-regex: + metavariable: $URLSTR + regex: .*://$ + - patterns: + - pattern: f"$URLSTR{...}..." + - metavariable-regex: + metavariable: $URLSTR + regex: .*://$ + - patterns: + - pattern-inside: | + $URL = "$URLSTR" + ... + - pattern: $URL += ... + - metavariable-regex: + metavariable: $URLSTR + regex: .*://$ + pattern-sources: + - patterns: + - pattern-either: + - pattern: flask.request.$ANYTHING + - patterns: + - pattern-inside: | + @$APP.route(...) + def $FUNC(..., $ROUTEVAR, ...): + ... + - pattern: $ROUTEVAR + severity: WARNING +- id: python.flask.security.injection.user-eval.eval-injection + languages: + - python + severity: ERROR + message: Detected user data flowing into eval. This is code injection and should be avoided. + metadata: + cwe: + - "CWE-95: Improper Neutralization of Directives in Dynamically Evaluated Code ('Eval Injection')" + owasp: + - A03:2021 - Injection + references: + - https://nedbatchelder.com/blog/201206/eval_really_is_dangerous.html + category: security + technology: + - flask + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + pattern-either: + - patterns: + - pattern: eval(...) + - pattern-either: + - pattern-inside: | + @$APP.route($ROUTE, ...) + def $FUNC(..., $ROUTEVAR, ...): + ... + eval(..., <... $ROUTEVAR ...>, ...) + - pattern-inside: | + @$APP.route($ROUTE, ...) + def $FUNC(..., $ROUTEVAR, ...): + ... + $INTERM = <... $ROUTEVAR ...> + ... + eval(..., <... $INTERM ...>, ...) + - pattern: eval(..., <... flask.request.$W.get(...) ...>, ...) + - pattern: eval(..., <... flask.request.$W[...] ...>, ...) + - pattern: eval(..., <... flask.request.$W(...) ...>, ...) + - pattern: eval(..., <... flask.request.$W ...>, ...) + - patterns: + - pattern-inside: | + $INTERM = <... flask.request.$W.get(...) ...> + ... + eval(..., <... $INTERM ...>, ...) + - pattern: eval(...) + - patterns: + - pattern-inside: | + $INTERM = <... flask.request.$W[...] ...> + ... + eval(..., <... $INTERM ...>, ...) + - pattern: eval(...) + - patterns: + - pattern-inside: | + $INTERM = <... flask.request.$W(...) ...> + ... + eval(..., <... $INTERM ...>, ...) + - pattern: eval(...) + - patterns: + - pattern-inside: | + $INTERM = <... flask.request.$W ...> + ... + eval(..., <... $INTERM ...>, ...) + - pattern: eval(...) +- id: python.flask.security.injection.user-exec.exec-injection + languages: + - python + severity: ERROR + message: Detected user data flowing into exec. This is code injection and should be avoided. + metadata: + cwe: + - "CWE-95: Improper Neutralization of Directives in Dynamically Evaluated Code ('Eval Injection')" + owasp: + - A03:2021 - Injection + references: + - https://nedbatchelder.com/blog/201206/exec_really_is_dangerous.html + category: security + technology: + - flask + subcategory: + - vuln + likelihood: MEDIUM + impact: HIGH + confidence: MEDIUM + pattern-either: + - patterns: + - pattern: exec(...) + - pattern-either: + - pattern-inside: | + @$APP.route($ROUTE, ...) + def $FUNC(..., $ROUTEVAR, ...): + ... + exec(..., <... $ROUTEVAR ...>, ...) + - pattern-inside: | + @$APP.route($ROUTE, ...) + def $FUNC(..., $ROUTEVAR, ...): + ... + $INTERM = <... $ROUTEVAR ...> + ... + exec(..., <... $INTERM ...>, ...) + - pattern: exec(..., <... flask.request.$W.get(...) ...>, ...) + - pattern: exec(..., <... flask.request.$W[...] ...>, ...) + - pattern: exec(..., <... flask.request.$W(...) ...>, ...) + - pattern: exec(..., <... flask.request.$W ...>, ...) + - patterns: + - pattern-inside: | + $INTERM = <... flask.request.$W.get(...) ...> + ... + exec(..., <... $INTERM ...>, ...) + - pattern: exec(...) + - patterns: + - pattern-inside: | + $INTERM = <... flask.request.$W[...] ...> + ... + exec(..., <... $INTERM ...>, ...) + - pattern: exec(...) + - patterns: + - pattern-inside: | + $INTERM = <... flask.request.$W(...) ...> + ... + exec(..., <... $INTERM ...>, ...) + - pattern: exec(...) + - patterns: + - pattern-inside: | + $INTERM = <... flask.request.$W ...> + ... + exec(..., <... $INTERM ...>, ...) + - pattern: exec(...) +- id: python.flask.security.insecure-deserialization.insecure-deserialization + metadata: + owasp: + - A08:2017 - Insecure Deserialization + - A08:2021 - Software and Data Integrity Failures + cwe: + - 'CWE-502: Deserialization of Untrusted Data' + references: + - https://docs.python.org/3/library/pickle.html + category: security + technology: + - flask + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + message: >- + Detected the use of an insecure deserialization library in a Flask route. These libraries + are prone to code execution vulnerabilities. Ensure user data does not enter this function. + To fix this, try to avoid serializing whole objects. Consider instead using a serializer + such as JSON. + languages: + - python + severity: ERROR + patterns: + - pattern-inside: | + @app.route(...) + def $X(...): + ... + - pattern-not: $MODULE.$FUNC("...") + - pattern-not: $MODULE.$FUNC(open("...", ...)) + - pattern-either: + - pattern: pickle.$FUNC(...) + - pattern: _pickle.$FUNC(...) + - pattern: cPickle.$FUNC(...) + - pattern: dill.$FUNC(...) + - pattern: shelve.$FUNC(...) + - pattern: yaml.load(...) +- id: python.flask.security.open-redirect.open-redirect + patterns: + - pattern-inside: | + @$APP.route(...) + def $X(...): + ... + - pattern-not-inside: | + @$APP.route(...) + def $X(...): + ... + if <... werkzeug.urls.url_parse($V) ...>: + ... + - pattern-either: + - pattern: flask.redirect(<... flask.request.$W.get(...) ...>, ...) + - pattern: flask.redirect(<... flask.request.$W[...] ...>, ...) + - pattern: flask.redirect(<... flask.request.$W(...) ...>, ...) + - pattern: flask.redirect(<... flask.request.$W ...>, ...) + - pattern: | + $V = flask.request.$W.get(...) + ... + flask.redirect(<... $V ...>, ...) + - pattern: | + $V = flask.request.$W[...] + ... + flask.redirect(<... $V ...>, ...) + - pattern: | + $V = flask.request.$W(...) + ... + flask.redirect(<... $V ...>, ...) + - pattern: | + $V = flask.request.$W + ... + flask.redirect(<... $V ...>, ...) + - pattern-not: flask.redirect(flask.request.path) + - pattern-not: flask.redirect(flask.request.path + ...) + - pattern-not: flask.redirect(f"{flask.request.path}...") + message: >- + Data from request is passed to redirect(). + This is an open redirect and could be exploited. + Consider using 'url_for()' to generate links to known locations. + If you must use a URL to unknown pages, consider using 'urlparse()' + or similar and checking if the 'netloc' property is the same as + your site's host name. See the references for more information. + metadata: + cwe: + - "CWE-601: URL Redirection to Untrusted Site ('Open Redirect')" + owasp: + - A01:2021 - Broken Access Control + references: + - https://flask-login.readthedocs.io/en/latest/#login-example + - https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html#dangerous-url-redirect-example-1 + - https://docs.python.org/3/library/urllib.parse.html#url-parsing + category: security + technology: + - flask + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + languages: [python] + severity: ERROR +- id: python.flask.security.secure-static-file-serve.avoid_send_file_without_path_sanitization + patterns: + - pattern-inside: | + @app.route(...) + def $X(filename): + ... + - pattern: flask.send_file(filename, ...) + message: Detected a user-controlled `filename` that could flow to `flask.send_file()` function. This + could lead to an attacker reading arbitrary file from the system, leaking private information. Make + sure to properly sanitize filename or use `flask.send_from_directory` + metadata: + cwe: + - 'CWE-73: External Control of File Name or Path' + owasp: + - A04:2021 - Insecure Design + category: security + technology: + - flask + references: + - https://owasp.org/Top10/A04_2021-Insecure_Design + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + languages: [python] + severity: WARNING +- id: python.flask.security.unescaped-template-extension.unescaped-template-extension + message: >- + Flask does not automatically escape Jinja templates unless they have + .html, .htm, .xml, or .xhtml extensions. This could lead to XSS attacks. + Use .html, .htm, .xml, or .xhtml for your template extensions. + See https://flask.palletsprojects.com/en/1.1.x/templating/#jinja-setup + for more information. + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + source-rule-url: https://pypi.org/project/flake8-flask/ + references: + - https://flask.palletsprojects.com/en/1.1.x/templating/#jinja-setup + - https://semgrep.dev/blog/2020/bento-check-unescaped-template-extensions-in-flask/ + - https://bento.dev/checks/flask/unescaped-file-extension/ + category: security + technology: + - flask + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + patterns: + - pattern-not: flask.render_template("=~/.+\.html$/", ...) + - pattern-not: flask.render_template("=~/.+\.xml$/", ...) + - pattern-not: flask.render_template("=~/.+\.htm$/", ...) + - pattern-not: flask.render_template("=~/.+\.xhtml$/", ...) + - pattern-not: flask.render_template($X + "=~/\.html$/", ...) + - pattern-not: flask.render_template($X + "=~/\.xml$/", ...) + - pattern-not: flask.render_template($X + "=~/\.htm$/", ...) + - pattern-not: flask.render_template($X + "=~/\.xhtml$/", ...) + - pattern-not: flask.render_template("=~/.+\.html$/" % $X, ...) + - pattern-not: flask.render_template("=~/.+\.xml$/" % $X, ...) + - pattern-not: flask.render_template("=~/.+\.htm$/" % $X, ...) + - pattern-not: flask.render_template("=~/.+\.xhtml$/" % $X, ...) + - pattern-not: flask.render_template("=~/.+\.html$/".format(...), ...) + - pattern-not: flask.render_template("=~/.+\.xml$/".format(...), ...) + - pattern-not: flask.render_template("=~/.+\.htm$/".format(...), ...) + - pattern-not: flask.render_template("=~/.+\.xhtml$/".format(...), ...) + - pattern-not: flask.render_template($TEMPLATE) + - pattern-either: + - pattern: flask.render_template("...", ...) + - pattern: flask.render_template($X + "...", ...) + - pattern: flask.render_template("..." % $Y, ...) + - pattern: flask.render_template("...".format(...), ...) + languages: [python] + severity: WARNING +- id: python.flask.security.unsanitized-input.response-contains-unsanitized-input + message: >- + Flask response reflects unsanitized user input. This could lead to a + cross-site scripting vulnerability (https://owasp.org/www-community/attacks/xss/) + in which an attacker causes arbitrary code to be executed in the user's browser. + To prevent, please sanitize the user input, e.g. by rendering the response + in a Jinja2 template (see considerations in https://flask.palletsprojects.com/en/1.0.x/security/). + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + references: + - https://flask.palletsprojects.com/en/1.0.x/security/ + - https://owasp.org/www-community/attacks/xss/ + category: security + technology: + - flask + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + languages: [python] + severity: WARNING + pattern-either: + - pattern: | + $X = flask.request.args.get(...) + ... + flask.make_response("...".format($X)) + - pattern: | + $X = flask.request.args.get(...) + ... + flask.make_response(f"...{$X}...") + - pattern: | + $X = flask.request.args.get(...) + ... + flask.make_response(f"...{$X}") + - pattern: | + $X = flask.request.args.get(...) + ... + flask.make_response(f"{$X}...") +- id: python.flask.security.xss.audit.direct-use-of-jinja2.direct-use-of-jinja2 + message: >- + Detected direct use of jinja2. If not done properly, + this may bypass HTML escaping which opens up the application to + cross-site scripting (XSS) vulnerabilities. Prefer using the Flask + method 'render_template()' and templates with a '.html' extension + in order to prevent XSS. + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + references: + - https://jinja.palletsprojects.com/en/2.11.x/api/#basics + category: security + technology: + - flask + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + languages: + - python + severity: WARNING + pattern-either: + - pattern: jinja2.Environment(...) + - pattern: jinja2.Template.render(...) + - patterns: + - pattern-inside: | + $TEMPLATE = $ENV.get_template(...) + ... + - pattern: $TEMPLATE.render(...) + - patterns: + - pattern-inside: | + $TEMPLATE = jinja2.Template(...) + ... + - pattern: $TEMPLATE.render(...) +- id: python.flask.security.xss.audit.explicit-unescape-with-markup.explicit-unescape-with-markup + message: >- + Detected explicitly unescaped content using 'Markup()'. This permits + the unescaped data to include unescaped HTML which could result in + cross-site scripting. Ensure this data is not externally controlled, + or consider rewriting to not use 'Markup()'. + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + references: + - https://tedboy.github.io/flask/generated/generated/flask.Markup.html + category: security + technology: + - flask + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + languages: + - python + severity: WARNING + pattern-either: + - pattern: flask.Markup.unescape(...) + - pattern: $MARKUPOBJ.unescape() + - patterns: + - pattern-either: + - pattern: flask.Markup($Q) + - pattern: markupsafe.Markup($Q) + - metavariable-pattern: + metavariable: $Q + patterns: + - pattern-not: '"..."' +- id: python.flask.security.xss.audit.template-autoescape-off.template-autoescape-off + message: >- + Detected a segment of a Flask template where autoescaping is explicitly + disabled with '{% autoescape off %}'. This allows rendering of raw HTML + in this segment. Ensure no user data is rendered here, otherwise this + is a cross-site scripting (XSS) vulnerability, or turn autoescape on. + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + references: + - https://flask.palletsprojects.com/en/1.1.x/templating/#controlling-autoescaping + - https://flask.palletsprojects.com/en/1.1.x/templating/#jinja-setup + category: security + technology: + - flask + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + languages: + - regex + paths: + include: + - '*.html' + severity: WARNING + pattern-regex: '{%\s*autoescape\s+false\s*%}' +- id: python.flask.security.xss.audit.template-href-var.template-href-var + message: >- + Detected a template variable used in an anchor tag with + the 'href' attribute. This allows a malicious actor to + input the 'javascript:' URI and is subject to cross- + site scripting (XSS) attacks. Use 'url_for()' to safely + generate a URL. You may also consider setting the Content + Security Policy (CSP) header. + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + references: + - https://flask.palletsprojects.com/en/1.1.x/security/#cross-site-scripting-xss + - https://content-security-policy.com/ + category: security + technology: + - flask + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + languages: + - generic + paths: + include: + - '*.html' + severity: WARNING + patterns: + - pattern-inside: + - pattern-either: + - pattern: href = {{ ... }} + - pattern: href = "{{ ... }}" + - pattern: href = '{{ ... }}' + - pattern-not-inside: href = {{ url_for(...) ... }} + - pattern-not-inside: href = "{{ url_for(...) ... }}" + - pattern-not-inside: href = '{{ url_for(...) ... }}' +- id: python.flask.security.xss.audit.template-unescaped-with-safe.template-unescaped-with-safe + message: >- + Detected a segment of a Flask template where autoescaping is explicitly + disabled with '| safe' filter. This allows rendering of raw HTML + in this segment. Ensure no user data is rendered here, otherwise this + is a cross-site scripting (XSS) vulnerability. + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + references: + - https://flask.palletsprojects.com/en/1.1.x/security/#cross-site-scripting-xss + category: security + technology: + - flask + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + languages: + - regex + paths: + include: + - '*.html' + severity: WARNING + pattern-regex: '{{.*?\|\s*safe(\s*}})?' +- id: python.flask.security.xss.audit.template-unquoted-attribute-var.template-unquoted-attribute-var + message: >- + Detected a unquoted template variable as an attribute. If unquoted, a + malicious actor could inject custom JavaScript handlers. To fix this, add + quotes around the template expression, like this: "{{ $...VAR }}". + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + references: + - https://flask.palletsprojects.com/en/1.1.x/security/#cross-site-scripting-xss + category: security + technology: + - flask + license: Commons Clause License Condition v1.0[LGPL-2.1-only] + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + languages: + - generic + paths: + include: + - '*.html' + - '*.py' + severity: WARNING + patterns: + - pattern: ={{$...VAR}} + - pattern-inside: | + <$TAG ... > + - metavariable-pattern: + metavariable: $...VAR + pattern-either: + - pattern: | + request.$VALUE.get(...) + - pattern: | + request.$VALUE['...'] + - patterns: + - pattern: $REQ + - pattern-either: + - pattern-inside: | + $REQ = request.$VALUE.get(...) + ... + - pattern-inside: | + $REQ = request.$VALUE['...'] + ... + fix: | + ="{{$...VAR}}" +- id: python.jinja2.security.audit.autoescape-disabled-false.incorrect-autoescape-disabled + patterns: + - pattern: jinja2.Environment(... , autoescape=$VAL, ...) + - pattern-not: jinja2.Environment(... , autoescape=True, ...) + - pattern-not: jinja2.Environment(... , autoescape=jinja2.select_autoescape(...), ...) + - focus-metavariable: $VAL + fix: | + True + message: >- + Detected a Jinja2 environment with 'autoescaping' disabled. + This is dangerous if you are rendering to a browser because this allows for cross-site + scripting (XSS) attacks. If you are in a web context, enable 'autoescaping' by setting + 'autoescape=True.' You may also consider using 'jinja2.select_autoescape()' to only enable + automatic escaping for certain file extensions. + metadata: + source-rule-url: https://bandit.readthedocs.io/en/latest/plugins/b701_jinja2_autoescape_false.html + cwe: + - 'CWE-116: Improper Encoding or Escaping of Output' + owasp: + - A03:2021 - Injection + references: + - https://jinja.palletsprojects.com/en/2.11.x/api/#basics + category: security + technology: + - jinja2 + subcategory: + - vuln + likelihood: LOW + impact: MEDIUM + confidence: MEDIUM + languages: [python] + severity: WARNING +- id: python.jinja2.security.audit.missing-autoescape-disabled.missing-autoescape-disabled + patterns: + - pattern-not: jinja2.Environment(..., autoescape=$VAL, ...) + - pattern: jinja2.Environment(...) + fix-regex: + regex: (.*)\) + replacement: \1, autoescape=True) + message: >- + Detected a Jinja2 environment without autoescaping. Jinja2 does not autoescape by default. + This is dangerous if you are rendering to a browser because this allows for cross-site + scripting (XSS) attacks. If you are in a web context, enable autoescaping by setting + 'autoescape=True.' You may also consider using 'jinja2.select_autoescape()' to only enable + automatic escaping for certain file extensions. + metadata: + source-rule-url: https://bandit.readthedocs.io/en/latest/plugins/b701_jinja2_autoescape_false.html + cwe: + - 'CWE-116: Improper Encoding or Escaping of Output' + owasp: + - A03:2021 - Injection + references: + - https://jinja.palletsprojects.com/en/2.11.x/api/#basics + category: security + technology: + - jinja2 + subcategory: + - vuln + likelihood: LOW + impact: MEDIUM + confidence: MEDIUM + languages: [python] + severity: WARNING +- id: python.jwt.security.audit.jwt-exposed-data.jwt-python-exposed-data + message: >- + The object is passed strictly to jwt.encode(...) + Make sure that sensitive information is not exposed through JWT token payload. + severity: WARNING + metadata: + owasp: + - A02:2017 - Broken Authentication + - A04:2021 - Insecure Design + cwe: + - 'CWE-522: Insufficiently Protected Credentials' + source-rule-url: https://semgrep.dev/blog/2020/hardcoded-secrets-unverified-tokens-and-other-common-jwt-mistakes/ + category: security + technology: + - jwt + references: + - https://owasp.org/Top10/A04_2021-Insecure_Design + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [python] + patterns: + - pattern-inside: | + def $FUNC(...,$INPUT,...): + ... + - pattern: |- + jwt.encode($INPUT,...) +- id: python.jwt.security.jwt-exposed-credentials.jwt-python-exposed-credentials + languages: + - python + metadata: + cwe: + - 'CWE-522: Insufficiently Protected Credentials' + owasp: + - A02:2017 - Broken Authentication + - A04:2021 - Insecure Design + source-rule-url: https://semgrep.dev/blog/2020/hardcoded-secrets-unverified-tokens-and-other-common-jwt-mistakes/ + references: + - https://cwe.mitre.org/data/definitions/522.html + category: security + technology: + - jwt + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + message: >- + Password is exposed through JWT token payload. This is not encrypted and + the password could be compromised. Do not store passwords in JWT tokens. + pattern-either: + - pattern: | + jwt.encode({...,"password":$P,...},...) + - pattern: | + $PAYLOAD = {...,"password":$P,...} + ... + jwt.encode($PAYLOAD,...) + severity: ERROR +- id: python.jwt.security.jwt-hardcode.jwt-python-hardcoded-secret + message: >- + Hardcoded JWT secret or private key is used. + This is a Insufficiently Protected Credentials weakness: https://cwe.mitre.org/data/definitions/522.html + Consider using an appropriate security mechanism to protect the credentials (e.g. keeping secrets + in environment variables) + metadata: + cwe: + - 'CWE-522: Insufficiently Protected Credentials' + owasp: + - A02:2017 - Broken Authentication + - A04:2021 - Insecure Design + references: + - https://semgrep.dev/blog/2020/hardcoded-secrets-unverified-tokens-and-other-common-jwt-mistakes/ + category: security + technology: + - jwt + cwe2021-top25: true + subcategory: + - vuln + likelihood: HIGH + impact: MEDIUM + confidence: HIGH + patterns: + - pattern: | + jwt.encode($X, $SECRET, ...) + - focus-metavariable: $SECRET + - pattern: | + "..." + languages: [python] + severity: ERROR +- id: python.jwt.security.jwt-none-alg.jwt-python-none-alg + message: >- + Detected use of the 'none' algorithm in a JWT token. + The 'none' algorithm assumes the integrity of the token has already + been verified. This would allow a malicious actor to forge a JWT token + that will automatically be verified. Do not explicitly use the 'none' + algorithm. Instead, use an algorithm such as 'HS256'. + metadata: + cwe: + - 'CWE-327: Use of a Broken or Risky Cryptographic Algorithm' + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + source-rule-url: https://semgrep.dev/blog/2020/hardcoded-secrets-unverified-tokens-and-other-common-jwt-mistakes/ + category: security + technology: + - jwt + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + languages: [python] + severity: ERROR + pattern-either: + - pattern: | + jwt.encode(...,algorithm="none",...) + - pattern: |- + jwt.decode(...,algorithms=[...,"none",...],...) +- id: python.jwt.security.unverified-jwt-decode.unverified-jwt-decode + patterns: + - pattern-either: + - patterns: + - pattern: | + jwt.decode(..., options={..., "verify_signature": $BOOL, ...}, ...) + - metavariable-pattern: + metavariable: $BOOL + pattern: | + False + - focus-metavariable: $BOOL + - patterns: + - pattern: | + $OPTS = {..., "verify_signature": $BOOL, ...} + ... + jwt.decode(..., options=$OPTS, ...) + - metavariable-pattern: + metavariable: $BOOL + pattern: | + False + - focus-metavariable: $BOOL + message: >- + Detected JWT token decoded with 'verify=False'. This bypasses any integrity + checks for the token which means the token could be tampered with by + malicious actors. Ensure that the JWT token is verified. + metadata: + owasp: + - A02:2017 - Broken Authentication + - A07:2021 - Identification and Authentication Failures + cwe: + - 'CWE-287: Improper Authentication' + references: + - https://github.com/we45/Vulnerable-Flask-App/blob/752ee16087c0bfb79073f68802d907569a1f0df7/app/app.py#L96 + category: security + technology: + - jwt + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + fix: | + True + severity: ERROR + languages: + - python +- id: python.lang.best-practice.hardcoded-tmp-path.hardcoded-tmp-path + pattern: open("=~/^\/tmp.*/", ...) + message: >- + Detected hardcoded temp directory. Consider using 'tempfile.TemporaryFile' instead. + metadata: + references: + - https://docs.python.org/3/library/tempfile.html#tempfile.TemporaryFile + category: best-practice + technology: + - python + severity: WARNING + languages: + - python +- id: python.lang.best-practice.logging-error-without-handling.logging-error-without-handling + patterns: + - pattern-inside: | + try: + ... + except ...: + ... + ... + - pattern-either: + - pattern: | + logger.$FUNC(...) + ... + raise + - pattern: | + logger.$FUNC(...) + ... + raise $EX + - pattern: | + logger.$FUNC(...) + ... + raise $EX from $EX2 + - metavariable-regex: + metavariable: $FUNC + regex: (error|exception) + message: Errors should only be logged when handled. The code logs the error and propogates the exception, consider reducing the level to warning or info. + languages: + - python + severity: WARNING + metadata: + category: best-practice + technology: + - python +- id: python.lang.best-practice.manual-collections-create.manual-defaultdict-dict-create + message: manually creating a defaultdict - use collections.defaultdict(dict) + languages: [python] + severity: WARNING + pattern-either: + - pattern: | + $DICT = {} + ... + for $KEY, $VALUE in $OTHERDICT.items(): + ... + if $KEY not in $DICT: + ... + $DICT[$KEY] = {} + ... + $DICT[$KEY].update(...) + - pattern: | + $DICT = {} + ... + for $KEY, $VALUE in $OTHERDICT.items(): + ... + $DICT.setdefault($KEY, {}).update(...) + metadata: + category: best-practice + technology: + - python +- id: python.lang.best-practice.manual-collections-create.manual-defaultdict-set-create + message: manually creating a defaultdict - use collections.defaultdict(set) + languages: [python] + severity: WARNING + pattern-either: + - pattern: | + $DICT = {} + ... + for $KEY, $VALUE in $OTHERDICT.items(): + ... + if $KEY not in $DICT: + ... + $DICT[$KEY] = set() + ... + $DICT[$KEY].add(...) + - pattern: | + $DICT = {} + ... + for $KEY, $VALUE in $OTHERDICT.items(): + ... + $DICT.setdefault($KEY, set()).add(...) + metadata: + category: best-practice + technology: + - python +- id: python.lang.best-practice.manual-collections-create.manual-defaultdict-list-create + message: manually creating a defaultdict - use collections.defaultdict(list) + languages: [python] + severity: WARNING + pattern-either: + - pattern: | + $DICT = {} + ... + for $KEY, $VALUE in $OTHERDICT.items(): + ... + if $KEY not in $DICT: + ... + $DICT[$KEY] = [] + ... + $DICT[$KEY].append(...) + - pattern: | + $DICT = {} + ... + for $KEY, $VALUE in $OTHERDICT.items(): + ... + $DICT.setdefault($KEY, []).append(...) + metadata: + category: best-practice + technology: + - python +- id: python.lang.best-practice.manual-collections-create.manual-counter-create + pattern: | + $DICT = {} + ... + for $KEY, $VALUE in $OTHERDICT.items(): + ... + if $KEY not in $DICT: + ... + $DICT[$KEY] = 0 + ... + $DICT[$KEY] += 1 + message: manually creating a counter - use collections.Counter + languages: [python] + severity: WARNING + metadata: + category: best-practice + technology: + - python +- id: python.lang.best-practice.missing-hash-with-eq.missing-hash-with-eq + patterns: + - pattern-not-inside: | + class A(...): + ... + def __hash__(self): + ... + ... + def __eq__(self, $O): + ... + - pattern: | + class A(...): + ... + def __eq__(self, $O): ... + ... + message: "Class `$A` has defined `__eq__` which means it should also have defined `__hash__`; " + languages: [python] + severity: WARNING + metadata: + category: best-practice + technology: + - python +- id: python.lang.best-practice.open-never-closed.open-never-closed + patterns: + - pattern-not-inside: | + $F = open(...) + ... + $F.close() + - pattern-not-inside: | + $F = io.open(...) + ... + $F.close() + - pattern-not-inside: | + $F = tarfile.open(...) + ... + $F.close() + - pattern-not-inside: | + $F = ZipFile.open(...) + ... + $F.close() + - pattern-not-inside: | + $F = tempfile.TemporaryFile(...) + ... + $F.close() + - pattern-not-inside: | + $F = tempfile.NamedTemporaryFile(...) + ... + $F.close() + - pattern-not-inside: | + $F = tempfile.SpooledTemporaryFile(...) + ... + $F.close() + - pattern-not-inside: | + $F = open(...) + ... + try: + ... + finally: + $F.close() + - pattern-not-inside: | + $F = io.open(...) + ... + try: + ... + finally: + $F.close() + - pattern-not-inside: | + $F = tarfile.open(...) + ... + try: + ... + finally: + $F.close() + - pattern-not-inside: | + $F = ZipFile.open(...) + ... + try: + ... + finally: + $F.close() + - pattern-not-inside: | + $F = tempfile.TemporaryFile(...) + ... + try: + ... + finally: + $F.close() + - pattern-not-inside: | + $F = tempfile.NamedTemporaryFile(...) + ... + try: + ... + finally: + $F.close() + - pattern-not-inside: | + $F = tempfile.SpooledTemporaryFile(...) + ... + try: + ... + finally: + $F.close() + - pattern-either: + - pattern: $F = open(...) + - pattern: $F = io.open(...) + - pattern: $F = tarfile.open(...) + - pattern: $F = ZipFile.open(...) + - pattern: $F = tempfile.TemporaryFile(...) + - pattern: $F = tempfile.NamedTemporaryFile(...) + - pattern: $F = tempfile.SpooledTemporaryFile(...) + message: file object opened without corresponding close + languages: [python] + severity: ERROR + metadata: + category: best-practice + technology: + - python +- id: python.lang.best-practice.pass-body.pass-body-fn + patterns: + - pattern-not-inside: | + def __init__(self, ...): + ... + - pattern-not-inside: | + class $A: + ... + - pattern: | + def $X(...): + pass + message: "`pass` is the body of function $X. Consider removing this or raise NotImplementedError() if this is a TODO" + languages: [python] + severity: WARNING + metadata: + category: best-practice + technology: + - python +- id: python.lang.best-practice.pass-body.pass-body-range + pattern: | + for $X in $Y: + pass + message: "`pass` is the body of for $X in $Y. Consider removing this or raise NotImplementedError() if this is a TODO" + languages: [python] + severity: WARNING + metadata: + category: best-practice + technology: + - python +- id: python.lang.best-practice.pdb.python-debugger-found + pattern-either: + - pattern: import pdb + - pattern: pdb.set_trace() + message: Importing the python debugger; did you mean to leave this in? + severity: WARNING + languages: + - python + metadata: + category: best-practice + technology: + - python +- id: python.lang.best-practice.sleep.arbitrary-sleep + patterns: + - pattern-not: time.sleep($F(...)) + - pattern-either: + - pattern: | + time.sleep($X: int) + - pattern: | + time.sleep($X: float) + message: time.sleep() call; did you mean to leave this in? + languages: [python] + severity: ERROR + metadata: + category: best-practice + technology: + - python +- id: python.lang.best-practice.unspecified-open-encoding.unspecified-open-encoding + patterns: + - pattern-inside: open(...) + - pattern-not: open(..., encoding="...", ...) + - pattern-not: open($F, "...", $B, "...", ...) + - pattern-either: + - pattern: open($FILE) + - patterns: + - pattern: open($FILE, ...) + - pattern-not: open($FILE, $M, ...) + - pattern-not-regex: open\(.*(?:encoding|mode)=.*\) + - patterns: + - pattern: open($FILE, $MODE, ...) + - metavariable-regex: + metavariable: $MODE + regex: (?!.*b.*) + - patterns: + - pattern: open($FILE, ..., mode=$MODE, ...) + - metavariable-regex: + metavariable: $MODE + regex: (?!.*b.*) + + message: >- + Missing 'encoding' parameter. + 'open()' uses device locale encodings by default, corrupting files with special characters. + Specify the encoding to ensure cross-platform support when opening files in text mode (e.g. encoding="utf-8"). + languages: [python] + severity: WARNING + metadata: + category: best-practice + technology: + - python + references: + - https://www.python.org/dev/peps/pep-0597/ + - https://docs.python.org/3/library/functions.html#open +- id: python.lang.compatibility.python36.python36-compatibility-ssl + pattern: ssl.get_ciphers() + message: this function is only available on Python 3.6+ + languages: [python] + severity: ERROR + metadata: + category: compatibility + technology: + - python +- id: python.lang.compatibility.python36.python36-compatibility-popen1 + pattern: subprocess.Popen(errors=$X, ...) + message: the `errors` argument to Popen is only available on Python 3.6+ + languages: [python] + severity: ERROR + metadata: + category: compatibility + technology: + - python +- id: python.lang.compatibility.python36.python36-compatibility-popen2 + pattern: subprocess.Popen(encoding=$X, ...) + message: the `encoding` argument to Popen is only available on Python 3.6+ + languages: [python] + severity: ERROR + metadata: + category: compatibility + technology: + - python +- id: python.lang.compatibility.python37.python37-compatibility-importlib + pattern: importlib.source_hash() + message: + source_hash' is only available on Python 3.7+. This does not work in lower versions, and therefore is not backwards + compatible. Instead, use another hash function. + languages: [python] + severity: ERROR + metadata: + category: compatibility + technology: + - python +- id: python.lang.compatibility.python37.python37-compatibility-importlib2 + pattern: import importlib.resources + message: + Found 'importlib.resources', which is a module only available on Python 3.7+. This does not work in lower versions, + and therefore is not backwards compatible. Use importlib_resources instead for older Python versions. + languages: [python] + severity: ERROR + metadata: + category: compatibility + technology: + - python +- id: python.lang.compatibility.python37.python37-compatibility-httpconn + pattern: http.client.HTTPConnection(blocksize=$X,...) + message: + Found usage of the 'blocksize' argument in a HTTPConnection call. This is only available on Python 3.7+ and is + therefore not backwards compatible. Remove this in order for this code to work in Python 3.6 and below. + languages: [python] + severity: ERROR + metadata: + category: compatibility + technology: + - python +- id: python.lang.compatibility.python37.python37-compatibility-httpsconn + pattern: http.client.HTTPSConnection(blocksize=$X,...) + message: + Found usage of the 'blocksize' argument in a HTTPSConnection call. This is only available on Python 3.7+ and is + therefore not backwards compatible. Remove this in order for this code to work in Python 3.6 and below. + languages: [python] + severity: ERROR + metadata: + category: compatibility + technology: + - python +- id: python.lang.compatibility.python37.python37-compatibility-importlib3 + pattern: import importlib.abc.ResourceReader + message: + Found usage of 'importlib.abc.ResourceReader'. This module is only available on Python 3.7+ and is therefore not + backwards compatible. Instead, use another loader. + languages: [python] + severity: ERROR + metadata: + category: compatibility + technology: + - python +- id: python.lang.compatibility.python37.python37-compatibility-textiowrapper + pattern: TextIOWrapper.reconfigure(...) + message: + Found usage of 'importlib.abc.ResourceReader'. This module is only available on Python 3.7+ and is therefore not + backwards compatible. Instead, use another loader. + languages: [python] + severity: ERROR + metadata: + category: compatibility + technology: + - python +- id: python.lang.compatibility.python37.python37-compatibility-ipv6network1 + pattern: ipaddress.IPv6Network.subnet_of($X) + message: + IPv6Network.subnet_of is only available on Python 3.7+ and is therefore not backwards compatible. Instead, check + if the subnet is in 'subnets'. + languages: [python] + severity: ERROR + metadata: + category: compatibility + technology: + - python +- id: python.lang.compatibility.python37.python37-compatibility-ipv6network2 + pattern: ipaddress.IPv6Network.supernet_of($X) + message: + IPv6Network.supernet_of is only available on Python 3.7+ and is therefore not backwards compatible. Instead, check + if the supernet is in 'supernet'. + languages: [python] + severity: ERROR + metadata: + category: compatibility + technology: + - python +- id: python.lang.compatibility.python37.python37-compatibility-ipv4network1 + pattern: ipaddress.IPv4Network.subnet_of($X) + message: + IPv4Network.subnet_of is only available on Python 3.7+ and is therefore not backwards compatible. Instead, check + if the subnet is in 'subnets'. + languages: [python] + severity: ERROR + metadata: + category: compatibility + technology: + - python +- id: python.lang.compatibility.python37.python37-compatibility-ipv4network2 + pattern: ipaddress.IPv4Network.supernet_of($X) + message: + IPv4Network.supernet_of is only available on Python 3.7+ and is therefore not backwards compatible. Instead, check + if the supernet is in 'supernet'. + languages: [python] + severity: ERROR + metadata: + category: compatibility + technology: + - python +- id: python.lang.compatibility.python37.python37-compatibility-locale1 + pattern: locale.format_string(monetary=$X, ...) + message: + Found usage of the 'monetary' argument in a function call of 'locale.format_string'. This is only available on + Python 3.7+ and is therefore not backwards compatible. Instead, remove the 'monetary' argument. + languages: [python] + severity: ERROR + metadata: + category: compatibility + technology: + - python +- id: python.lang.compatibility.python37.python37-compatibility-math1 + pattern: math.remainder($X, $Y) + message: + math.remainder is only available on Python 3.7+ and is therefore not backwards compatible. Instead, use math.fmod() + or calculate $X - n* $Y. + languages: [python] + severity: ERROR + metadata: + category: compatibility + technology: + - python +- id: python.lang.compatibility.python37.python37-compatibility-multiprocess1 + pattern: multiprocessing.Process.close() + message: + multiprocessing.Process.close() is only available on Python 3.7+ and is therefore not backwards compatible. Instead, + use join(). + languages: [python] + severity: ERROR + metadata: + category: compatibility + technology: + - python +- id: python.lang.compatibility.python37.python37-compatibility-multiprocess2 + pattern: multiprocessing.Process.kill() + message: + multiprocessing.Process.kill() is only available on Python 3.7+ and is therefore not backwards compatible. Instead, + use terminate(). + languages: [python] + severity: ERROR + metadata: + category: compatibility + technology: + - python +- id: python.lang.compatibility.python37.python37-compatibility-os1 + pattern: os.preadv(...) + message: + os.preadv() is only available on Python 3.7+ and is therefore not backwards compatible. Instead, use a combination + of os.readv() and os.pread(). + languages: [python] + severity: ERROR + metadata: + category: compatibility + technology: + - python +- id: python.lang.compatibility.python37.python37-compatibility-os2-ok2 + patterns: + - pattern-not-inside: | + if hasattr(os, 'pwritev'): + ... + - pattern: os.pwritev(...) + message: + os.pwritev() is only available on Python 3.3+ and is therefore not backwards compatible. Instead, use a combination + of pwrite() and writev(). + languages: [python] + severity: ERROR + metadata: + category: compatibility + technology: + - python +- id: python.lang.compatibility.python37.python37-compatibility-pdb + pattern: pdb.set_trace(header=$X, ...) + message: + pdb.set_trace() with the header argument is only available on Python 3.7+ and is therefore not backwards compatible. + Instead, use set_trace() without the header argument. + languages: [python] + severity: ERROR + metadata: + category: compatibility + technology: + - python +- id: python.lang.correctness.baseclass-attribute-override.baseclass-attribute-override + message: >- + Class $C inherits from both `$A` and `$B` which both have a method named + `$F`; one of these methods will be overwritten. + languages: [python] + severity: WARNING + patterns: + - pattern-inside: | + class $A(...): + ... + def $F(...): + ... + ... + ... + - pattern-inside: | + class $B(...): + ... + def $F(...): + ... + ... + ... + - pattern: | + class $C(..., $A, ..., $B, ...): + ... + - focus-metavariable: $C + metadata: + category: correctness + references: + - https://docs.python.org/3/tutorial/classes.html#multiple-inheritance + technology: + - python +- id: python.lang.correctness.cannot-cache-generators.cannot-cache-generators + patterns: + - pattern-inside: | + @functools.lru_cache(...) + def $FUNC(...): + ... + yield ... + - pattern: functools.lru_cache(...) + message: Generators can only be consumed once, so in most cases, caching them will + cause an error when the already-consumed generator is retrieved from cache. + languages: + - python + severity: WARNING + metadata: + category: correctness + technology: [python] +- id: python.lang.correctness.common-mistakes.default-mutable-dict.default-mutable-dict + message: >- + Function $F mutates default dict $D. Python only instantiates default function + arguments once and shares the + instance across the function calls. If the default function argument is mutated, + that will modify the + instance used by all future function calls. This can cause + unexpected results, or lead to security vulnerabilities whereby one function consumer + can view or modify the data + of another function consumer. Instead, use a default argument (like None) to indicate + that no argument was provided + and instantiate a new dictionary at that time. For example: `if $D is None: $D + = {}`. + languages: [python] + severity: ERROR + options: + symbolic_propagation: true + patterns: + - pattern-not-inside: | + def $A(...): + ... + def $F(..., $D={}, ...): + ... + - pattern-inside: | + def $F(..., $D={}, ...): + ... + - pattern-not-inside: | + $D = {} + ... + - pattern-not-inside: | + $D = dict(...) + ... + - pattern-not-inside: | + $D = $D.copy() + ... + - pattern-not-inside: | + $D = copy.deepcopy($D) + ... + - pattern-not-inside: | + $D = copy.copy($D) + ... + - pattern-not-inside: | + $D = dict.copy($D) + ... + - pattern-not-inside: | + $D = {... for ... in ...} + ... + - pattern-not-inside: | + $D = $D or {} + ... + - pattern-either: + - pattern: | + $D[...] = ... + - pattern: | + $D.update(...) + - pattern: | + $D.setdefault(...) + metadata: + category: correctness + technology: + - python + references: + - https://docs.python-guide.org/writing/gotchas/#mutable-default-arguments +- id: python.lang.correctness.common-mistakes.default-mutable-list.default-mutable-list + message: >- + Function $F mutates default list $D. Python only instantiates default function + arguments once and shares the + instance across the function calls. If the default function argument is mutated, + that will modify the + instance used by all future function calls. This can cause + unexpected results, or lead to security vulnerabilities whereby one function consumer + can view or modify the data + of another function consumer. Instead, use a default argument (like None) to indicate + that no argument was provided + and instantiate a new list at that time. For example: `if $D is None: $D = []`. + languages: [python] + severity: ERROR + options: + symbolic_propagation: true + patterns: + - pattern-not-inside: | + def $A(...): + ... + def $F(..., $D=[], ...): + ... + - pattern-inside: | + def $F(..., $D=[], ...): + ... + - pattern-not-inside: | + $D = [] + ... + - pattern-not-inside: | + $D = [...] + ... + - pattern-not-inside: | + $D = list(...) + ... + - pattern-not-inside: | + $D = copy.deepcopy($D) + ... + - pattern-not-inside: | + $D = copy.copy($D) + ... + - pattern-not-inside: | + $D = list.copy($D) + ... + - pattern-not-inside: | + $D = $D[:] + ... + - pattern-not-inside: | + $D = [... for ... in ...] + ... + - pattern-not-inside: | + $D = $D or [] + ... + - pattern-either: + - pattern: | + $D.append(...) + - pattern: | + $D.extend(...) + - pattern: | + $D.insert(...) + metadata: + category: correctness + technology: + - python + references: + - https://docs.python-guide.org/writing/gotchas/#mutable-default-arguments +- id: python.lang.correctness.common-mistakes.is-comparison-string.identical-is-comparison + pattern: $S is $S + message: Found identical comparison using is. Ensure this is what you intended. + languages: [python] + severity: ERROR + metadata: + category: correctness + technology: + - python +- id: python.lang.correctness.common-mistakes.is-comparison-string.string-is-comparison + patterns: + - pattern-not: $S is None + - pattern-not: type($X) is $T + - pattern-not: $S is True + - pattern-not: $S is False + - pattern-not: $S is "" + - pattern-either: + - pattern: $S is "..." + # quotes needed b/c YAML complains if starting with "..." + - pattern: '"..." is $S' + message: >- + Found string comparison using 'is' operator. The 'is' operator + is for reference equality, not value equality, and therefore should + not be used to compare strings. For more information, see + https://github.com/satwikkansal/wtfpython#-how-not-to-use-is-operator" + languages: [python] + severity: ERROR + metadata: + category: correctness + technology: + - python +- id: python.lang.correctness.common-mistakes.is-not-is-not.is-not-is-not + message: >- + In Python 'X is not ...' is different from 'X is (not ...)'. + In the latter the 'not' converts the '...' directly to boolean. + languages: [python] + severity: ERROR + pattern: $S is (not ...) + metadata: + category: correctness + technology: + - python +- id: python.lang.correctness.common-mistakes.string-concat-in-list.string-concat-in-list + patterns: + - pattern-either: + - pattern-inside: "[...]" + - pattern-inside: "{...}" + - pattern: '"..." "..."' + - pattern-not-inside: f"..." + - pattern-not-inside: "{..., $KEY: $VALUE, ...}" + message: >- + Detected strings that are implicitly concatenated inside a list. + Python will implicitly concatenate strings when not explicitly delimited. + Was this supposed to be individual elements of the list? + severity: WARNING + languages: + - python + metadata: + category: correctness + technology: + - python +- id: python.lang.correctness.concurrent.uncaught-executor-exceptions + patterns: + - pattern-inside: | + with concurrent.futures.thread.ThreadPoolExecutor(...) as $EXECUTOR: + ... + - pattern-not-inside: | + $VAR = $EXECUTOR.map(...) + ... + for ... in $VAR: + ... + - pattern-not-inside: | + $VAR = $EXECUTOR.map(...) + ... + [... for ... in $VAR] + - pattern-not-inside: | + [... for ... in $EXECUTOR.map(...)] + - pattern-not-inside: | + for $IT in $EXECUTOR.map(...): + ... + - pattern: $EXECUTOR.map(...) + message: >- + Values returned by thread pool map must be read in order to raise exceptions. + Consider using `for _ in $EXECUTOR.map(...): pass`. + severity: WARNING + languages: + - python + metadata: + references: + - https://superfastpython.com/threadpoolexecutor-exception-handling/ + category: correctness + technology: + - python +- id: python.lang.correctness.dict-modify-iterating.dict-del-while-iterate + message: + "It appears that `$DICT[$KEY]` is a dict with items being deleted while in a for loop. This is usually a bad idea + and will likely lead to a RuntimeError: dictionary changed size during iteration" + metadata: + references: + - https://docs.python.org/3/library/stdtypes.html#dictionary-view-objects + category: correctness + technology: + - python + languages: [python] + severity: WARNING + pattern-either: + - pattern: | + for $KEY, $VALUE in $DICT.items(): + ... + del $DICT[$KEY] + - pattern: | + for $KEY in $DICT.keys(): + ... + del $DICT[$KEY] +- id: python.lang.correctness.exceptions.exceptions.raise-not-base-exception + message: + In Python3, a runtime `TypeError` will be thrown if you attempt to raise an object or class which does not inherit + from `BaseException` + languages: [python] + severity: ERROR + pattern-either: + - pattern: raise "..." + - pattern: | + $X: BaseException + raise $X(...) + - patterns: + - pattern: raise $EXCEPTION + - metavariable-regex: + metavariable: $EXCEPTION + regex: '[0-9]*\.?[0-9]+' + metadata: + category: correctness + technology: + - python +- id: python.lang.correctness.exit.use-sys-exit + languages: + - python + message: + Detected use of `exit`. + Use `sys.exit` over the python shell `exit` built-in. `exit` is a helper for the interactive shell and may not + be available on all Python implementations. + patterns: + - pattern: exit($X) + - pattern-not: sys.exit($X) + severity: WARNING + fix: sys.exit($X) + metadata: + category: correctness + technology: + - python + references: + - https://stackoverflow.com/questions/6501121/difference-between-exit-and-sys-exit-in-python +- id: python.lang.correctness.file-object-redefined-before-close.file-object-redefined-before-close + patterns: + - pattern: | + $F = open($X, ...) + ... + $F = open($Y, ...) + - pattern-not: | + $F = open($X, ...) + ... + $F.close() + ... + $F = open($Y, ...) + message: >- + Detected a file object that is redefined and never closed. This + could leak file descriptors and unnecessarily consume system resources. + languages: [python] + severity: WARNING + metadata: + category: correctness + technology: + - python +- id: python.lang.correctness.list-modify-iterating.list-modify-while-iterate + message: >- + It appears that `$LIST` is a list that is being modified while in a for loop. + This will likely cause a runtime error or an infinite loop. + languages: [python] + severity: ERROR + pattern-either: + - pattern: | + for $ELEMENT in $LIST: + ... + $LIST.pop(...) + - pattern: | + for $ELEMENT in $LIST: + ... + $LIST.push(...) + - pattern: | + for $ELEMENT in $LIST: + ... + $LIST.append(...) + - pattern: | + for $ELEMENT in $LIST: + ... + $LIST.extend(...) + - pattern: | + for $ELEMENT in $LIST: + ... + $LIST.remove(...) + metadata: + category: correctness + technology: + - python + references: + - https://unspecified.wordpress.com/2009/02/12/thou-shalt-not-modify-a-list-during-iteration/ +- id: python.lang.correctness.pdb.pdb-remove + pattern-either: + - pattern: pdb.$X(...) + - pattern: pdb.Pdb.$X(...) + message: >- + pdb is an interactive debugging tool and you may have forgotten to remove it before + committing your code + languages: [python] + severity: WARNING + metadata: + category: correctness + technology: + - python +- id: python.lang.correctness.pytest-assert_match-after-path-patch.pytest-assert_match-after-path-patch + patterns: + - pattern-inside: | + import pytest + ... + - pattern-either: + - pattern-inside: | + mocker.patch("pathlib.Path", $MOCKED_VALUE) + ... + - pattern-inside: | + mocker.patch.object(pathlib.Path, $METHOD, $MOCKED_VALUE) + ... + - pattern: + snapshot.assert_match(...) + message: >- + snapshot.assert_match makes use of pathlib to create files. Patching $METHOD may result in unexpected snapshot behavior + languages: [python] + severity: WARNING + metadata: + category: correctness + technology: + - python + references: + - https://github.com/returntocorp/semgrep/pull/5459 + - https://pypi.org/project/pytest-snapshot/ +- id: python.lang.correctness.return-in-init.return-in-init + patterns: + - pattern-inside: | + class $A(...): + ... + - pattern-inside: | + def __init__(...): + ... + - pattern-not-inside: | + def __init__(...): + ... + def $F(...): + ... + - patterns: + - pattern: return ... + - pattern-not: return + - pattern-not: return None + message: "`return` should never appear inside a class __init__ function. This will cause a runtime error." + languages: [python] + severity: ERROR + metadata: + category: correctness + technology: + - python +- id: python.lang.correctness.return-in-init.yield-in-init + patterns: + - pattern-inside: | + class $A(...): + ... + - pattern-inside: | + def __init__(...): + ... + - pattern-not-inside: | + def __init__(...): + ... + def $F(...): + ... + - pattern-either: + - pattern: yield ... + - pattern: yield + message: "`yield` should never appear inside a class __init__ function. This will cause a runtime error." + languages: [python] + severity: ERROR + metadata: + category: correctness + technology: + - python +- id: python.lang.correctness.sync-sleep-in-async-code.sync-sleep-in-async-code + patterns: + - pattern: time.sleep(...) + - pattern-inside: | + async def $F(...): + ... + - pattern-not-inside: | + async def $F(...): + def $INNER(...): + ... + message: Synchronous time.sleep in async code will block the event loop and not allow other tasks to execute. Use asyncio.sleep() instead. + languages: [python] + severity: WARNING + metadata: + category: best-practice + technology: + - python +- id: python.lang.correctness.tempfile.flush.tempfile-without-flush + languages: + - python + message: + Using '$F.name' without '.flush()' or '.close()' may cause an error because the file may not exist when '$F.name' + is used. Use '.flush()' or close the file before using '$F.name'. + pattern-either: + - patterns: + - pattern-not-inside: | + $F = tempfile.NamedTemporaryFile(...) + ... + $F.write(...) + ... + $F.flush() + ... + $F.name + - pattern-not-inside: | + $F = tempfile.NamedTemporaryFile(...) + ... + $F.write(...) + ... + $F.close() + ... + $F.name + - pattern-not-inside: | + $F = tempfile.NamedTemporaryFile(..., delete=False, ...) + ... + $F.close() + ... + $F.name + - pattern-inside: | + $F = tempfile.NamedTemporaryFile(...) + ... + - pattern: | + $F.name + - patterns: + - pattern-not-inside: | + with tempfile.NamedTemporaryFile(...) as $F: + ... + $F.write(...) + ... + $F.flush() + ... + $F.name + - pattern-not-inside: | + with tempfile.NamedTemporaryFile(...) as $F: + ... + $F.write(...) + ... + $F.close() + ... + $F.name + - pattern-not-inside: | + with tempfile.NamedTemporaryFile(...) as $F: + ... + $MODULE.dump(..., $F, ...) + ... + $F.flush() + ... + $F.name + - pattern-not-inside: | + with tempfile.NamedTemporaryFile(...) as $F: + ... + $MODULE.dump(..., $F, ...) + ... + $F.close() + ... + $F.name + - pattern-inside: | + with tempfile.NamedTemporaryFile(...) as $F: + ... + - pattern: | + $F.name + severity: ERROR + metadata: + category: correctness + technology: + - python +- id: python.lang.correctness.tempfile.mktemp.tempfile-insecure + pattern: tempfile.mktemp(...) + message: + "Use tempfile.NamedTemporaryFile instead. From the official Python documentation: THIS FUNCTION IS UNSAFE AND SHOULD + NOT BE USED. The file name may refer to a file that did not exist at some point, but by the time you get around to creating + it, someone else may have beaten you to the punch." + languages: [python] + severity: ERROR + metadata: + category: correctness + technology: + - python +- id: python.lang.correctness.test-is-missing-assert.test-is-missing-assert + languages: + - python + message: >- + Comparison without assertion. The result of this + comparison is not used. Perhaps this expression + is missing an `assert` keyword. + patterns: + - pattern: $A == $B + - pattern-not-inside: assert ... + - pattern-not-inside: $X = ... + - pattern-not-inside: $X += ... + - pattern-not-inside: $X |= ... + - pattern-not-inside: $X &= ... + - pattern-not-inside: yield $X + - pattern-not-inside: $X and $Y + - pattern-not-inside: $X or $Y + - pattern-not-inside: return ... + - pattern-not-inside: $FUNC(...) + - pattern-not-inside: | + while $EXPR: + ... + - pattern-not-inside: | + with (...): + ... + - pattern-not-inside: | + [...] + - pattern-not-inside: | + $EXPR[...] + - pattern-not-inside: | + if ...: + ... + severity: WARNING + paths: + include: + - test*.py + metadata: + category: correctness + technology: + - python +- id: python.lang.correctness.unchecked-returns.unchecked-subprocess-call + patterns: + - pattern: subprocess.$CALL(...) + - pattern-not-inside: $S = subprocess.call(...) + - pattern-not-inside: subprocess.call(...) == $X + - pattern-not-inside: return subprocess.call(...) + - metavariable-pattern: + metavariable: $CALL + pattern: call + - focus-metavariable: $CALL + fix: check_call + message: + This is not checking the return value of this subprocess call; if it fails no exception will be raised. Consider + subprocess.check_call() instead + languages: [python] + severity: WARNING + metadata: + references: + - https://docs.python.org/3/library/subprocess.html#subprocess.check_call + category: correctness + technology: + - python +- id: python.lang.correctness.useless-comparison.no-strings-as-booleans + message: >- + Using strings as booleans in Python has unexpected results. + `"one" and "two"` will return "two". + `"one" or "two"` will return "one". + In Python, strings are truthy, and strings with a non-zero length evaluate to + True. + languages: [python] + severity: ERROR + pattern-either: + - pattern: | + if <... "..." and ... ...>: + ... + - pattern: | + if <... "..." or ... ...>: + ... + - patterns: + - pattern-not: | + if $X in "...": + ... + - pattern: | + if "...": + ... + metadata: + category: correctness + technology: + - python +- id: python.lang.correctness.useless-eqeq.useless-eqeq + patterns: + - pattern-not-inside: | + def __eq__(...): + ... + - pattern-not-inside: | + def __cmp__(...): + ... + - pattern-not-inside: assert(...) + - pattern-not-inside: assert ..., ... + - pattern-not-inside: assertTrue(...) + - pattern-not-inside: assertFalse(...) + - pattern-either: + - pattern: $X == $X + - pattern: $X != $X + - pattern-not: 1 == 1 + message: >- + This expression is always True: `$X == $X` or `$X != $X`. + If testing for floating point NaN, use `math.isnan($X)`, + or `cmath.isnan($X)` if the number is complex. + languages: [python] + severity: INFO + metadata: + category: correctness + technology: + - python +- id: python.lang.correctness.writing-to-file-in-read-mode.writing-to-file-in-read-mode + message: >- + The file object '$FD' was opened in read mode, but is being + written to. This will cause a runtime error. + patterns: + - pattern-either: + - pattern-inside: | + $FD = open($NAME, "r", ...) + ... + - pattern-inside: | + $FD = open($NAME, "rb", ...) + ... + - pattern-inside: | + with open($NAME, "r", ...) as $FD: + ... + - pattern-inside: | + with open($NAME, "rb", ...) as $FD: + ... + - pattern: $FD.write(...) + severity: ERROR + languages: + - python + metadata: + category: correctness + technology: + - python +- id: python.lang.maintainability.improper-list-concat.improper-list-concat + languages: + - python + message: >- + This expression will evaluate to be ONLY value the of the `else` clause if the + condition `$EXPRESSION` + is false. If you meant to do list concatenation, put parentheses around the entire + concatenation expression, like + this: `['a', 'b', 'c'] + (['d'] if x else ['e'])`. If this is the intended behavior, + the expression may be confusing to + others, and you may wish to add parentheses for readability. + metadata: + category: maintainability + technology: + - python + pattern: "[...] + [...] if $EXPRESSION else [...]" + severity: INFO +- id: python.lang.maintainability.is-function-without-parentheses.is-function-without-parentheses + languages: + - python + message: + Is "$FUNC" a function or an attribute? If it is a function, you may have meant $X.$FUNC() because $X.$FUNC is always + true. + patterns: + - pattern: $X.$FUNC + - pattern-not-inside: $X.$FUNC(...) + - metavariable-regex: + metavariable: $FUNC + regex: is_.* + severity: WARNING + metadata: + category: maintainability + technology: + - python +- id: python.lang.maintainability.return.code-after-unconditional-return + pattern: | + return ... + $S + message: code after return statement will not be executed + languages: [python] + severity: WARNING + metadata: + category: maintainability + technology: + - python +- id: python.lang.maintainability.return.return-not-in-function + patterns: + - pattern-not-inside: | + def $F(...): + ... + # TODO: first pattern should just automatically include this one + - pattern-not-inside: | + def $F(...) -> $Y: + ... + - pattern: return ... + message: "`return` only makes sense inside a function" + languages: [python] + severity: WARNING + metadata: + category: maintainability + technology: + - python +- id: python.lang.maintainability.useless-assign-keyed.useless-assignment-keyed + message: key `$Y` in `$X` is assigned twice; the first assignment is useless + languages: [python] + severity: INFO + pattern-either: + - pattern: | + $X[$Y] = ... + $X[$Y] = ... + - pattern: | + $X[$Y][$Z] = ... + $X[$Y][$Z] = ... + metadata: + category: maintainability + technology: + - python +- id: python.lang.maintainability.useless-ifelse.useless-if-conditional + message: if block checks for the same condition on both branches (`$X`) + languages: [python] + severity: WARNING + pattern: | + if $X: + ... + elif $X: + ... + metadata: + references: + - https://docs.python.org/3/tutorial/controlflow.html + category: maintainability + technology: + - python +- id: python.lang.maintainability.useless-ifelse.useless-if-body + pattern: | + if $X: + $S + else: + $S + message: Useless if statement; both blocks have the same body + languages: [python] + severity: WARNING + metadata: + references: + - https://docs.python.org/3/tutorial/controlflow.html + category: maintainability + technology: + - python +- id: python.lang.maintainability.useless-innerfunction.useless-inner-function + patterns: + - pattern-not-inside: | + def $F(...): + ... + def $FF(...): + ... + ... + <... $FF ...> + - pattern-not-inside: | + def $F(...): + ... + class $CLAZZ(...): + ... + - pattern-inside: | + def $F(...): + ... + def $FF(...): + ... + ... + - pattern: | + def $FF(...): + ... + - pattern-not: | + @$DECORATOR + def $FF(...): + ... + message: function `$FF` is defined inside a function but never used + languages: + - python + severity: ERROR + metadata: + category: maintainability + technology: + - python + license: Commons Clause License Condition v1.0[LGPL-2.1-only] +- id: python.lang.maintainability.useless-literal-set.useless-literal-set + patterns: + - pattern: | + set(..., ($X, $A), ..., ($X, $B), ...) + - focus-metavariable: $X + message: "`$X` is uselessly assigned twice inside the creation of the set" + languages: [python] + severity: ERROR + metadata: + category: maintainability + references: + - https://docs.python.org/3/library/stdtypes.html#set-types-set-frozenset + technology: + - python +- id: python.lang.maintainability.useless-literal.useless-literal + message: key `$X` is uselessly assigned twice + languages: [python] + severity: WARNING + patterns: + - pattern-either: + - pattern: | + {..., $X: $A, ..., $X: $B, ...} + - pattern: | + dict(..., ($X, $A), ..., ($X, $B), ...) + - focus-metavariable: $X + metadata: + category: maintainability + references: + - https://docs.python.org/3/library/stdtypes.html#mapping-types-dict + technology: + - python +- id: python.lang.security.audit.conn_recv.multiprocessing-recv + languages: + - python + message: 'The Connection.recv() method automatically unpickles the data it receives, which can be a + security risk unless you can trust the process which sent the message. Therefore, unless the connection + object was produced using Pipe() you should only use the recv() and send() methods after performing + some sort of authentication. See more dettails: https://docs.python.org/3/library/multiprocessing.html?highlight=security#multiprocessing.connection.Connection' + metadata: + cwe: + - 'CWE-502: Deserialization of Untrusted Data' + owasp: + - A08:2017 - Insecure Deserialization + - A08:2021 - Software and Data Integrity Failures + references: + - https://docs.python.org/3/library/multiprocessing.html?highlight=security#multiprocessing.connection.Connection + category: security + technology: + - python + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + pattern-either: + - pattern: multiprocessing.connection.Connection.recv(...) + - pattern: multiprocessing.connection.Client.recv(...) + - pattern: | + $C = multiprocessing.connection.Client(...) + ... + $C.recv(...) + severity: WARNING +- id: python.lang.security.audit.dangerous-annotations-usage.dangerous-annotations-usage + patterns: + - pattern: | + $C.__annotations__[$NAME] = $X + - pattern-not: | + $C.__annotations__[$NAME] = "..." + - pattern-not: | + $C.__annotations__[$NAME] = typing.$Y + - metavariable-regex: + metavariable: $X + regex: (?!(int|float|complex|list|tuple|range|str|bytes|bytearray|memoryview|set|frozenset|dict)) + message: Annotations passed to `typing.get_type_hints` are evaluated in `globals` and `locals` namespaces. + Make sure that no arbitrary value can be written as the annotation and passed to `typing.get_type_hints` + function. + severity: INFO + metadata: + cwe: + - "CWE-95: Improper Neutralization of Directives in Dynamically Evaluated Code ('Eval Injection')" + owasp: + - A03:2021 - Injection + category: security + references: + - https://docs.python.org/3/library/typing.html#typing.get_type_hints + technology: + - python + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: + - python +- id: python.lang.security.audit.dangerous-asyncio-create-exec-audit.dangerous-asyncio-create-exec-audit + pattern-either: + - patterns: + - pattern-not: asyncio.create_subprocess_exec($PROG, "...", ...) + - pattern-not: asyncio.create_subprocess_exec($PROG, ["...",...], ...) + - pattern: asyncio.create_subprocess_exec(...) + - patterns: + - pattern-not: asyncio.create_subprocess_exec($PROG, "=~/(sh|bash|ksh|csh|tcsh|zsh)/", "-c", "...", + ...) + - pattern: asyncio.create_subprocess_exec($PROG, "=~/(sh|bash|ksh|csh|tcsh|zsh)/", "-c",...) + - patterns: + - pattern-not: asyncio.create_subprocess_exec($PROG, ["=~/(sh|bash|ksh|csh|tcsh|zsh)/", "-c", "...", + ...], ...) + - pattern: asyncio.create_subprocess_exec($PROG, ["=~/(sh|bash|ksh|csh|tcsh|zsh)/", "-c", ...], ...) + - patterns: + - pattern-not: asyncio.subprocess.create_subprocess_exec($PROG, "...", ...) + - pattern-not: asyncio.subprocess.create_subprocess_exec($PROG, ["...",...], ...) + - pattern: asyncio.subprocess.create_subprocess_exec(...) + - patterns: + - pattern-not: asyncio.subprocess.create_subprocess_exec($PROG, "=~/(sh|bash|ksh|csh|tcsh|zsh)/", + "-c", "...", ...) + - pattern: asyncio.subprocess.create_subprocess_exec($PROG, "=~/(sh|bash|ksh|csh|tcsh|zsh)/", "-c",...) + - patterns: + - pattern-not: asyncio.subprocess.create_subprocess_exec($PROG, ["=~/(sh|bash|ksh|csh|tcsh|zsh)/", + "-c", "...", ...], ...) + - pattern: asyncio.subprocess.create_subprocess_exec($PROG, ["=~/(sh|bash|ksh|csh|tcsh|zsh)/", "-c", + ...], ...) + message: >- + Detected 'create_subprocess_exec' function without a static string. If this data + can be + controlled by a malicious actor, it may be an instance of command injection. + Audit the use of this call to ensure it is not controllable by an external resource. + You may consider using 'shlex.escape()'. + metadata: + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + cwe: + - "CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')" + asvs: + section: 'V5: Validation, Sanitization and Encoding Verification Requirements' + control_id: 5.3.8 OS Command Injection + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x13-V5-Validation-Sanitization-Encoding.md#v53-output-encoding-and-injection-prevention-requirements + version: '4' + references: + - https://docs.python.org/3/library/asyncio-subprocess.html#asyncio.create_subprocess_exec + - https://docs.python.org/3/library/shlex.html + - https://semgrep.dev/docs/cheat-sheets/python-command-injection/ + category: security + technology: + - python + confidence: LOW + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH + languages: [python] + severity: ERROR +- id: python.lang.security.audit.dangerous-asyncio-create-exec-tainted-env-args.dangerous-asyncio-create-exec-tainted-env-args + mode: taint + options: + symbolic_propagation: true + pattern-sources: + - patterns: + - pattern-either: + - patterns: + - pattern-either: + - pattern: os.environ + - pattern: os.environ.get('$FOO', ...) + - pattern: os.environb + - pattern: os.environb.get('$FOO', ...) + - pattern: os.getenv('$ANYTHING', ...) + - pattern: os.getenvb('$ANYTHING', ...) + - patterns: + - pattern-either: + - patterns: + - pattern-either: + - pattern: sys.argv + - pattern: sys.orig_argv + - patterns: + - pattern-inside: | + $PARSER = argparse.ArgumentParser(...) + ... + - pattern-inside: | + $ARGS = $PARSER.parse_args() + - pattern: <... $ARGS ...> + - patterns: + - pattern-inside: | + $PARSER = optparse.OptionParser(...) + ... + - pattern-inside: | + $ARGS = $PARSER.parse_args() + - pattern: <... $ARGS ...> + - patterns: + - pattern-either: + - pattern-inside: | + $OPTS, $ARGS = getopt.getopt(...) + ... + - pattern-inside: | + $OPTS, $ARGS = getopt.gnu_getopt(...) + ... + - pattern-either: + - patterns: + - pattern-inside: | + for $O, $A in $OPTS: + ... + - pattern: $A + - pattern: $ARGS + pattern-sinks: + - pattern-either: + - patterns: + - pattern-not: asyncio.create_subprocess_exec($PROG, "...", ...) + - pattern-not: asyncio.create_subprocess_exec($PROG, ["...",...], ...) + - pattern: asyncio.create_subprocess_exec(...) + - patterns: + - pattern-not: asyncio.create_subprocess_exec($PROG, "=~/(sh|bash|ksh|csh|tcsh|zsh)/", "-c", "...", + ...) + - pattern: asyncio.create_subprocess_exec($PROG, "=~/(sh|bash|ksh|csh|tcsh|zsh)/", "-c",...) + - patterns: + - pattern-not: asyncio.create_subprocess_exec($PROG, ["=~/(sh|bash|ksh|csh|tcsh|zsh)/", "-c", "...", + ...], ...) + - pattern: asyncio.create_subprocess_exec($PROG, ["=~/(sh|bash|ksh|csh|tcsh|zsh)/", "-c", ...], + ...) + - patterns: + - pattern-not: asyncio.subprocess.create_subprocess_exec($PROG, "...", ...) + - pattern-not: asyncio.subprocess.create_subprocess_exec($PROG, ["...",...], ...) + - pattern: asyncio.subprocess.create_subprocess_exec(...) + - patterns: + - pattern-not: asyncio.subprocess.create_subprocess_exec($PROG, "=~/(sh|bash|ksh|csh|tcsh|zsh)/", + "-c", "...", ...) + - pattern: asyncio.subprocess.create_subprocess_exec($PROG, "=~/(sh|bash|ksh|csh|tcsh|zsh)/", "-c",...) + - patterns: + - pattern-not: asyncio.subprocess.create_subprocess_exec($PROG, ["=~/(sh|bash|ksh|csh|tcsh|zsh)/", + "-c", "...", ...], ...) + - pattern: asyncio.subprocess.create_subprocess_exec($PROG, ["=~/(sh|bash|ksh|csh|tcsh|zsh)/", "-c", + ...], ...) + message: >- + Detected 'create_subprocess_exec' function with user controlled data. + You may consider using 'shlex.escape()'. + metadata: + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + cwe: + - "CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')" + asvs: + section: 'V5: Validation, Sanitization and Encoding Verification Requirements' + control_id: 5.3.8 OS Command Injection + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x13-V5-Validation-Sanitization-Encoding.md#v53-output-encoding-and-injection-prevention-requirements + version: '4' + references: + - https://docs.python.org/3/library/asyncio-subprocess.html#asyncio.create_subprocess_exec + - https://docs.python.org/3/library/shlex.html + - https://semgrep.dev/docs/cheat-sheets/python-command-injection/ + category: security + technology: + - python + confidence: LOW + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: LOW + impact: MEDIUM + languages: [python] + severity: ERROR +- id: python.lang.security.audit.dangerous-asyncio-exec-audit.dangerous-asyncio-exec-audit + pattern-either: + - patterns: + - pattern-not: $LOOP.subprocess_exec($PROTOCOL, "...", ...) + - pattern-not: $LOOP.subprocess_exec($PROTOCOL, ["...",...], ...) + - pattern: $LOOP.subprocess_exec(...) + - patterns: + - pattern-not: $LOOP.subprocess_exec($PROTOCOL, "=~/(sh|bash|ksh|csh|tcsh|zsh)/", "-c", "...", ...) + - pattern: $LOOP.subprocess_exec($PROTOCOL, "=~/(sh|bash|ksh|csh|tcsh|zsh)/", "-c",...) + - patterns: + - pattern-not: $LOOP.subprocess_exec($PROTOCOL, ["=~/(sh|bash|ksh|csh|tcsh|zsh)/", "-c", "...", ...], + ...) + - pattern: $LOOP.subprocess_exec($PROTOCOL, ["=~/(sh|bash|ksh|csh|tcsh|zsh)/", "-c", ...], ...) + message: >- + Detected subprocess function '$LOOP.subprocess_exec' without a static string. + If this data can be + controlled by a malicious actor, it may be an instance of command injection. + Audit the use of this call to ensure it is not controllable by an external resource. + You may consider using 'shlex.escape()'. + metadata: + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + cwe: + - "CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')" + asvs: + section: 'V5: Validation, Sanitization and Encoding Verification Requirements' + control_id: 5.3.8 OS Command Injection + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x13-V5-Validation-Sanitization-Encoding.md#v53-output-encoding-and-injection-prevention-requirements + version: '4' + references: + - https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.loop.subprocess_exec + - https://docs.python.org/3/library/shlex.html + - https://semgrep.dev/docs/cheat-sheets/python-command-injection/ + category: security + technology: + - python + confidence: LOW + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH + languages: [python] + severity: ERROR +- id: python.lang.security.audit.dangerous-asyncio-exec-tainted-env-args.dangerous-asyncio-exec-tainted-env-args + mode: taint + options: + symbolic_propagation: true + pattern-sources: + - patterns: + - pattern-either: + - patterns: + - pattern-either: + - pattern: os.environ + - pattern: os.environ.get('$FOO', ...) + - pattern: os.environb + - pattern: os.environb.get('$FOO', ...) + - pattern: os.getenv('$ANYTHING', ...) + - pattern: os.getenvb('$ANYTHING', ...) + - patterns: + - pattern-either: + - patterns: + - pattern-either: + - pattern: sys.argv + - pattern: sys.orig_argv + - patterns: + - pattern-inside: | + $PARSER = argparse.ArgumentParser(...) + ... + - pattern-inside: | + $ARGS = $PARSER.parse_args() + - pattern: <... $ARGS ...> + - patterns: + - pattern-inside: | + $PARSER = optparse.OptionParser(...) + ... + - pattern-inside: | + $ARGS = $PARSER.parse_args() + - pattern: <... $ARGS ...> + - patterns: + - pattern-either: + - pattern-inside: | + $OPTS, $ARGS = getopt.getopt(...) + ... + - pattern-inside: | + $OPTS, $ARGS = getopt.gnu_getopt(...) + ... + - pattern-either: + - patterns: + - pattern-inside: | + for $O, $A in $OPTS: + ... + - pattern: $A + - pattern: $ARGS + pattern-sinks: + - pattern-either: + - patterns: + - pattern-not: $LOOP.subprocess_exec($PROTOCOL, "...", ...) + - pattern-not: $LOOP.subprocess_exec($PROTOCOL, ["...",...], ...) + - pattern: $LOOP.subprocess_exec(...) + - patterns: + - pattern-not: $LOOP.subprocess_exec($PROTOCOL, "=~/(sh|bash|ksh|csh|tcsh|zsh)/", "-c", "...", ...) + - pattern: $LOOP.subprocess_exec($PROTOCOL, "=~/(sh|bash|ksh|csh|tcsh|zsh)/", "-c",...) + - patterns: + - pattern-not: $LOOP.subprocess_exec($PROTOCOL, ["=~/(sh|bash|ksh|csh|tcsh|zsh)/", "-c", "...", + ...], ...) + - pattern: $LOOP.subprocess_exec($PROTOCOL, ["=~/(sh|bash|ksh|csh|tcsh|zsh)/", "-c", ...], ...) + message: >- + Detected subprocess function '$LOOP.subprocess_exec' with user controlled data. + You may consider using 'shlex.escape()'. + metadata: + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + cwe: + - "CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')" + asvs: + section: 'V5: Validation, Sanitization and Encoding Verification Requirements' + control_id: 5.3.8 OS Command Injection + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x13-V5-Validation-Sanitization-Encoding.md#v53-output-encoding-and-injection-prevention-requirements + version: '4' + references: + - https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.loop.subprocess_exec + - https://docs.python.org/3/library/shlex.html + - https://semgrep.dev/docs/cheat-sheets/python-command-injection/ + category: security + technology: + - python + confidence: MEDIUM + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: HIGH + languages: [python] + severity: ERROR +- id: python.lang.security.audit.dangerous-asyncio-shell-audit.dangerous-asyncio-shell-audit + patterns: + - pattern-either: + - pattern: $LOOP.subprocess_shell($PROTOCOL, $CMD) + - pattern: asyncio.subprocess.create_subprocess_shell($CMD, ...) + - pattern: asyncio.create_subprocess_shell($CMD, ...) + - pattern-not-inside: | + $CMD = "..." + ... + - pattern-not: $LOOP.subprocess_shell($PROTOCOL, "...") + - pattern-not: asyncio.subprocess.create_subprocess_shell("...", ...) + - pattern-not: asyncio.create_subprocess_shell("...", ...) + message: >- + Detected asyncio subprocess function without a static string. If this data can + be + controlled by a malicious actor, it may be an instance of command injection. + Audit the use of this call to ensure it is not controllable by an external resource. + You may consider using 'shlex.escape()'. + metadata: + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + cwe: + - "CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')" + asvs: + section: 'V5: Validation, Sanitization and Encoding Verification Requirements' + control_id: 5.3.8 OS Command Injection + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x13-V5-Validation-Sanitization-Encoding.md#v53-output-encoding-and-injection-prevention-requirements + version: '4' + references: + - https://docs.python.org/3/library/asyncio-subprocess.html + - https://docs.python.org/3/library/shlex.html + - https://semgrep.dev/docs/cheat-sheets/python-command-injection/ + category: security + technology: + - python + confidence: LOW + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH + languages: + - python + severity: ERROR +- id: python.lang.security.audit.dangerous-asyncio-shell-tainted-env-args.dangerous-asyncio-shell-tainted-env-args + mode: taint + options: + symbolic_propagation: true + pattern-sources: + - patterns: + - pattern-either: + - patterns: + - pattern-either: + - pattern: os.environ + - pattern: os.environ.get('$FOO', ...) + - pattern: os.environb + - pattern: os.environb.get('$FOO', ...) + - pattern: os.getenv('$ANYTHING', ...) + - pattern: os.getenvb('$ANYTHING', ...) + - patterns: + - pattern-either: + - patterns: + - pattern-either: + - pattern: sys.argv + - pattern: sys.orig_argv + - patterns: + - pattern-inside: | + $PARSER = argparse.ArgumentParser(...) + ... + - pattern-inside: | + $ARGS = $PARSER.parse_args() + - pattern: <... $ARGS ...> + - patterns: + - pattern-inside: | + $PARSER = optparse.OptionParser(...) + ... + - pattern-inside: | + $ARGS = $PARSER.parse_args() + - pattern: <... $ARGS ...> + - patterns: + - pattern-either: + - pattern-inside: | + $OPTS, $ARGS = getopt.getopt(...) + ... + - pattern-inside: | + $OPTS, $ARGS = getopt.gnu_getopt(...) + ... + - pattern-either: + - patterns: + - pattern-inside: | + for $O, $A in $OPTS: + ... + - pattern: $A + - pattern: $ARGS + pattern-sinks: + - patterns: + - pattern-either: + - pattern-inside: $LOOP.subprocess_shell($PROTOCOL, $CMD) + - pattern-inside: asyncio.subprocess.create_subprocess_shell($CMD, ...) + - pattern-inside: asyncio.create_subprocess_shell($CMD, ...) + - focus-metavariable: $CMD + - pattern-not-inside: | + $CMD = "..." + ... + - pattern-not: $LOOP.subprocess_shell($PROTOCOL, "...") + - pattern-not: asyncio.subprocess.create_subprocess_shell("...", ...) + - pattern-not: asyncio.create_subprocess_shell("...", ...) + message: >- + Detected asyncio subprocess function with user controlled data. + You may consider using 'shlex.escape()'. + metadata: + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + cwe: + - "CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')" + asvs: + section: 'V5: Validation, Sanitization and Encoding Verification Requirements' + control_id: 5.3.8 OS Command Injection + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x13-V5-Validation-Sanitization-Encoding.md#v53-output-encoding-and-injection-prevention-requirements + version: '4' + references: + - https://docs.python.org/3/library/asyncio-subprocess.html + - https://docs.python.org/3/library/shlex.html + - https://semgrep.dev/docs/cheat-sheets/python-command-injection/ + category: security + technology: + - python + confidence: MEDIUM + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: HIGH + languages: + - python + severity: ERROR +- id: python.lang.security.audit.dangerous-code-run-audit.dangerous-interactive-code-run-audit + patterns: + - pattern-either: + - pattern: | + $X.push($PAYLOAD,...) + - pattern: | + $X.runsource($PAYLOAD,...) + - pattern: | + $X.runcode(code.compile_command($PAYLOAD),...) + - pattern: | + $PL = code.compile_command($PAYLOAD,...) + ... + $X.runcode($PL,...) + - pattern-either: + - pattern-inside: | + $X = code.InteractiveConsole(...) + ... + - pattern-inside: | + $X = code.InteractiveInterpreter(...) + ... + - pattern-not: | + $X.push("...",...) + - pattern-not: | + $X.runsource("...",...) + - pattern-not: | + $X.runcode(code.compile_command("..."),...) + - pattern-not: | + $PL = code.compile_command("...",...) + ... + $X.runcode($PL,...) + message: >- + Found dynamic content inside InteractiveConsole/InteractiveInterpreter method. + This is dangerous if external data can reach this function call because it allows + a malicious actor to run arbitrary Python code. + Ensure no external data reaches here. + metadata: + cwe: + - "CWE-95: Improper Neutralization of Directives in Dynamically Evaluated Code ('Eval Injection')" + owasp: + - A03:2021 - Injection + references: + - https://semgrep.dev/docs/cheat-sheets/python-command-injection/ + category: security + technology: + - python + confidence: LOW + subcategory: + - audit + likelihood: LOW + impact: HIGH + severity: WARNING + languages: + - python +- id: python.lang.security.audit.dangerous-code-run-tainted-env-args.dangerous-interactive-code-run-tainted-env-args + mode: taint + options: + symbolic_propagation: true + pattern-sources: + - patterns: + - pattern-either: + - patterns: + - pattern-either: + - pattern: os.environ + - pattern: os.environ.get('$FOO', ...) + - pattern: os.environb + - pattern: os.environb.get('$FOO', ...) + - pattern: os.getenv('$ANYTHING', ...) + - pattern: os.getenvb('$ANYTHING', ...) + - patterns: + - pattern-either: + - patterns: + - pattern-either: + - pattern: sys.argv + - pattern: sys.orig_argv + - patterns: + - pattern-inside: | + $PARSER = argparse.ArgumentParser(...) + ... + - pattern-inside: | + $ARGS = $PARSER.parse_args() + - pattern: <... $ARGS ...> + - patterns: + - pattern-inside: | + $PARSER = optparse.OptionParser(...) + ... + - pattern-inside: | + $ARGS = $PARSER.parse_args() + - pattern: <... $ARGS ...> + - patterns: + - pattern-either: + - pattern-inside: | + $OPTS, $ARGS = getopt.getopt(...) + ... + - pattern-inside: | + $OPTS, $ARGS = getopt.gnu_getopt(...) + ... + - pattern-either: + - patterns: + - pattern-inside: | + for $O, $A in $OPTS: + ... + - pattern: $A + - pattern: $ARGS + pattern-sinks: + - patterns: + - pattern-either: + - pattern-inside: | + $X = code.InteractiveConsole(...) + ... + - pattern-inside: | + $X = code.InteractiveInterpreter(...) + ... + - pattern-either: + - pattern-inside: | + $X.push($PAYLOAD,...) + - pattern-inside: | + $X.runsource($PAYLOAD,...) + - pattern-inside: | + $X.runcode(code.compile_command($PAYLOAD),...) + - pattern-inside: | + $PL = code.compile_command($PAYLOAD,...) + ... + $X.runcode($PL,...) + - pattern: $PAYLOAD + - pattern-not: | + $X.push("...",...) + - pattern-not: | + $X.runsource("...",...) + - pattern-not: | + $X.runcode(code.compile_command("..."),...) + - pattern-not: | + $PL = code.compile_command("...",...) + ... + $X.runcode($PL,...) + message: >- + Found user controlled data inside InteractiveConsole/InteractiveInterpreter method. + This is dangerous if external data can reach this function call because it allows + a malicious actor to run arbitrary Python code. + metadata: + cwe: + - "CWE-95: Improper Neutralization of Directives in Dynamically Evaluated Code ('Eval Injection')" + owasp: + - A03:2021 - Injection + references: + - https://semgrep.dev/docs/cheat-sheets/python-command-injection/ + category: security + technology: + - python + confidence: MEDIUM + subcategory: + - vuln + likelihood: MEDIUM + impact: HIGH + severity: WARNING + languages: + - python +- id: python.lang.security.audit.dangerous-os-exec-audit.dangerous-os-exec-audit + message: >- + Found dynamic content when spawning a process. This is dangerous if external + data can reach this function call because it allows a malicious actor to + execute commands. Ensure no external data reaches here. + metadata: + cwe: + - "CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')" + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + references: + - https://semgrep.dev/docs/cheat-sheets/python-command-injection/ + asvs: + section: 'V5: Validation, Sanitization and Encoding Verification Requirements' + control_id: 5.3.8 OS Command Injection + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x13-V5-Validation-Sanitization-Encoding.md#v53-output-encoding-and-injection-prevention-requirements + version: '4' + category: security + technology: + - python + confidence: LOW + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH + languages: [python] + severity: ERROR + pattern-either: + - patterns: + - pattern-not: os.$METHOD("...", ...) + - pattern: os.$METHOD(...) + - metavariable-regex: + metavariable: $METHOD + regex: (execl|execle|execlp|execlpe|execv|execve|execvp|execvpe) + - patterns: + - pattern-not: os.$METHOD("...", [$PATH,"...","...",...],...) + - pattern: os.$METHOD($BASH,[$PATH,"-c",$CMD,...],...) + - metavariable-regex: + metavariable: $METHOD + regex: (execv|execve|execvp|execvpe) + - metavariable-regex: + metavariable: $BASH + regex: (.*)(sh|bash|ksh|csh|tcsh|zsh) + - patterns: + - pattern-not: os.$METHOD("...", $PATH, "...", "...",...) + - pattern: os.$METHOD($BASH, $PATH, "-c", $CMD,...) + - metavariable-regex: + metavariable: $METHOD + regex: (execl|execle|execlp|execlpe) + - metavariable-regex: + metavariable: $BASH + regex: (.*)(sh|bash|ksh|csh|tcsh|zsh) +- id: python.lang.security.audit.dangerous-os-exec-tainted-env-args.dangerous-os-exec-tainted-env-args + mode: taint + options: + symbolic_propagation: true + pattern-sources: + - patterns: + - pattern-either: + - patterns: + - pattern-either: + - pattern: os.environ + - pattern: os.environ.get('$FOO', ...) + - pattern: os.environb + - pattern: os.environb.get('$FOO', ...) + - pattern: os.getenv('$ANYTHING', ...) + - pattern: os.getenvb('$ANYTHING', ...) + - patterns: + - pattern-either: + - patterns: + - pattern-either: + - pattern: sys.argv + - pattern: sys.orig_argv + - patterns: + - pattern-inside: | + $PARSER = argparse.ArgumentParser(...) + ... + - pattern-inside: | + $ARGS = $PARSER.parse_args() + - pattern: <... $ARGS ...> + - patterns: + - pattern-inside: | + $PARSER = optparse.OptionParser(...) + ... + - pattern-inside: | + $ARGS = $PARSER.parse_args() + - pattern: <... $ARGS ...> + - patterns: + - pattern-either: + - pattern-inside: | + $OPTS, $ARGS = getopt.getopt(...) + ... + - pattern-inside: | + $OPTS, $ARGS = getopt.gnu_getopt(...) + ... + - pattern-either: + - patterns: + - pattern-inside: | + for $O, $A in $OPTS: + ... + - pattern: $A + - pattern: $ARGS + pattern-sinks: + - patterns: + - pattern-either: + - patterns: + - pattern-not: os.$METHOD("...", ...) + - pattern: os.$METHOD(...) + - metavariable-regex: + metavariable: $METHOD + regex: (execl|execle|execlp|execlpe|execv|execve|execvp|execvpe) + - patterns: + - pattern-not: os.$METHOD("...", [$PATH,"...","...",...],...) + - pattern-inside: os.$METHOD($BASH,[$PATH,"-c",$CMD,...],...) + - pattern: $CMD + - metavariable-regex: + metavariable: $METHOD + regex: (execv|execve|execvp|execvpe) + - metavariable-regex: + metavariable: $BASH + regex: (.*)(sh|bash|ksh|csh|tcsh|zsh) + - patterns: + - pattern-not: os.$METHOD("...", $PATH, "...", "...",...) + - pattern-inside: os.$METHOD($BASH, $PATH, "-c", $CMD,...) + - pattern: $CMD + - metavariable-regex: + metavariable: $METHOD + regex: (execl|execle|execlp|execlpe) + - metavariable-regex: + metavariable: $BASH + regex: (.*)(sh|bash|ksh|csh|tcsh|zsh) + message: >- + Found user controlled content when spawning a process. This is dangerous because it allows + a malicious actor to execute commands. + metadata: + cwe: + - "CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')" + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + references: + - https://semgrep.dev/docs/cheat-sheets/python-command-injection/ + asvs: + section: 'V5: Validation, Sanitization and Encoding Verification Requirements' + control_id: 5.3.8 OS Command Injection + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x13-V5-Validation-Sanitization-Encoding.md#v53-output-encoding-and-injection-prevention-requirements + version: '4' + confidence: MEDIUM + category: security + technology: + - python + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: HIGH + languages: [python] + severity: ERROR +- id: python.lang.security.audit.dangerous-spawn-process-audit.dangerous-spawn-process-audit + message: >- + Found dynamic content when spawning a process. This is dangerous if external + data can reach this function call because it allows a malicious actor to + execute commands. Ensure no external data reaches here. + metadata: + source-rule-url: https://bandit.readthedocs.io/en/latest/plugins/b605_start_process_with_a_shell.html + cwe: + - "CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')" + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + references: + - https://semgrep.dev/docs/cheat-sheets/python-command-injection/ + asvs: + section: 'V5: Validation, Sanitization and Encoding Verification Requirements' + control_id: 5.3.8 OS Command Injection + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x13-V5-Validation-Sanitization-Encoding.md#v53-output-encoding-and-injection-prevention-requirements + version: '4' + category: security + technology: + - python + confidence: LOW + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH + languages: [python] + severity: ERROR + pattern-either: + - patterns: + - pattern-not: os.$METHOD($MODE, "...", ...) + - pattern: os.$METHOD(...) + - metavariable-regex: + metavariable: $METHOD + regex: (spawnl|spawnle|spawnlp|spawnlpe|spawnv|spawnve|spawnvp|spawnvp|spawnvpe|posix_spawn|posix_spawnp|startfile) + - patterns: + - pattern-not: os.$METHOD($MODE, "...", ["...","...",...], ...) + - pattern: os.$METHOD($MODE, $BASH, ["-c",$CMD,...],...) + - metavariable-regex: + metavariable: $METHOD + regex: (spawnv|spawnve|spawnvp|spawnvp|spawnvpe|posix_spawn|posix_spawnp) + - metavariable-regex: + metavariable: $BASH + regex: (.*)(sh|bash|ksh|csh|tcsh|zsh) + - patterns: + - pattern-not: os.$METHOD($MODE, "...", "...", "...", ...) + - pattern: os.$METHOD($MODE, $BASH, "-c", $CMD,...) + - metavariable-regex: + metavariable: $METHOD + regex: (spawnl|spawnle|spawnlp|spawnlpe) + - metavariable-regex: + metavariable: $BASH + regex: (.*)(sh|bash|ksh|csh|tcsh|zsh) +- id: python.lang.security.audit.dangerous-spawn-process-tainted-env-args.dangerous-spawn-process-tainted-env-args + mode: taint + options: + symbolic_propagation: true + pattern-sources: + - patterns: + - pattern-either: + - patterns: + - pattern-either: + - pattern: os.environ + - pattern: os.environ.get('$FOO', ...) + - pattern: os.environb + - pattern: os.environb.get('$FOO', ...) + - pattern: os.getenv('$ANYTHING', ...) + - pattern: os.getenvb('$ANYTHING', ...) + - patterns: + - pattern-either: + - patterns: + - pattern-either: + - pattern: sys.argv + - pattern: sys.orig_argv + - patterns: + - pattern-inside: | + $PARSER = argparse.ArgumentParser(...) + ... + - pattern-inside: | + $ARGS = $PARSER.parse_args() + - pattern: <... $ARGS ...> + - patterns: + - pattern-inside: | + $PARSER = optparse.OptionParser(...) + ... + - pattern-inside: | + $ARGS = $PARSER.parse_args() + - pattern: <... $ARGS ...> + - patterns: + - pattern-either: + - pattern-inside: | + $OPTS, $ARGS = getopt.getopt(...) + ... + - pattern-inside: | + $OPTS, $ARGS = getopt.gnu_getopt(...) + ... + - pattern-either: + - patterns: + - pattern-inside: | + for $O, $A in $OPTS: + ... + - pattern: $A + - pattern: $ARGS + pattern-sinks: + - patterns: + - pattern-either: + - patterns: + - pattern-not: os.$METHOD($MODE, "...", ...) + - pattern-inside: os.$METHOD($MODE, $CMD, ...) + - pattern: $CMD + - metavariable-regex: + metavariable: $METHOD + regex: (spawnl|spawnle|spawnlp|spawnlpe|spawnv|spawnve|spawnvp|spawnvp|spawnvpe|posix_spawn|posix_spawnp|startfile) + - patterns: + - pattern-not: os.$METHOD($MODE, "...", ["...","...",...], ...) + - pattern-inside: os.$METHOD($MODE, $BASH, ["-c",$CMD,...],...) + - pattern: $CMD + - metavariable-regex: + metavariable: $METHOD + regex: (spawnv|spawnve|spawnvp|spawnvp|spawnvpe|posix_spawn|posix_spawnp) + - metavariable-regex: + metavariable: $BASH + regex: (.*)(sh|bash|ksh|csh|tcsh|zsh) + - patterns: + - pattern-not: os.$METHOD($MODE, "...", "...", "...", ...) + - pattern-inside: os.$METHOD($MODE, $BASH, "-c", $CMD,...) + - pattern: $CMD + - metavariable-regex: + metavariable: $METHOD + regex: (spawnl|spawnle|spawnlp|spawnlpe) + - metavariable-regex: + metavariable: $BASH + regex: (.*)(sh|bash|ksh|csh|tcsh|zsh) + message: >- + Found user controlled content when spawning a process. This is dangerous because it allows a malicious + actor to + execute commands. + metadata: + source-rule-url: https://bandit.readthedocs.io/en/latest/plugins/b605_start_process_with_a_shell.html + cwe: + - "CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')" + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + references: + - https://semgrep.dev/docs/cheat-sheets/python-command-injection/ + asvs: + section: 'V5: Validation, Sanitization and Encoding Verification Requirements' + control_id: 5.3.8 OS Command Injection + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x13-V5-Validation-Sanitization-Encoding.md#v53-output-encoding-and-injection-prevention-requirements + version: '4' + category: security + technology: + - python + confidence: MEDIUM + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: HIGH + languages: [python] + severity: ERROR +- id: python.lang.security.audit.dangerous-subinterpreters-run-string-audit.dangerous-subinterpreters-run-string-audit + patterns: + - pattern: | + _xxsubinterpreters.run_string($ID, $PAYLOAD, ...) + - pattern-not: | + _xxsubinterpreters.run_string($ID, "...", ...) + message: >- + Found dynamic content in `run_string`. + This is dangerous if external data can reach this function call because it allows + a malicious actor to run arbitrary Python code. + Ensure no external data reaches here. + metadata: + cwe: + - "CWE-95: Improper Neutralization of Directives in Dynamically Evaluated Code ('Eval Injection')" + owasp: + - A03:2021 - Injection + references: + - https://bugs.python.org/issue43472 + - https://semgrep.dev/docs/cheat-sheets/python-command-injection/ + category: security + technology: + - python + confidence: LOW + subcategory: + - audit + likelihood: LOW + impact: HIGH + severity: WARNING + languages: + - python +- id: python.lang.security.audit.dangerous-subinterpreters-run-string-tainted-env-args.dangerous-subinterpreters-run-string-tainted-env-args + mode: taint + options: + symbolic_propagation: true + pattern-sources: + - patterns: + - pattern-either: + - patterns: + - pattern-either: + - pattern: os.environ + - pattern: os.environ.get('$FOO', ...) + - pattern: os.environb + - pattern: os.environb.get('$FOO', ...) + - pattern: os.getenv('$ANYTHING', ...) + - pattern: os.getenvb('$ANYTHING', ...) + - patterns: + - pattern-either: + - patterns: + - pattern-either: + - pattern: sys.argv + - pattern: sys.orig_argv + - patterns: + - pattern-inside: | + $PARSER = argparse.ArgumentParser(...) + ... + - pattern-inside: | + $ARGS = $PARSER.parse_args() + - pattern: <... $ARGS ...> + - patterns: + - pattern-inside: | + $PARSER = optparse.OptionParser(...) + ... + - pattern-inside: | + $ARGS = $PARSER.parse_args() + - pattern: <... $ARGS ...> + - patterns: + - pattern-either: + - pattern-inside: | + $OPTS, $ARGS = getopt.getopt(...) + ... + - pattern-inside: | + $OPTS, $ARGS = getopt.gnu_getopt(...) + ... + - pattern-either: + - patterns: + - pattern-inside: | + for $O, $A in $OPTS: + ... + - pattern: $A + - pattern: $ARGS + pattern-sinks: + - patterns: + - pattern-inside: | + _xxsubinterpreters.run_string($ID, $PAYLOAD, ...) + - pattern-not: | + _xxsubinterpreters.run_string($ID, "...", ...) + - pattern: $PAYLOAD + message: >- + Found user controlled content in `run_string`. + This is dangerous because it allows a malicious actor to run arbitrary Python code. + metadata: + cwe: + - "CWE-95: Improper Neutralization of Directives in Dynamically Evaluated Code ('Eval Injection')" + owasp: + - A03:2021 - Injection + references: + - https://bugs.python.org/issue43472 + - https://semgrep.dev/docs/cheat-sheets/python-command-injection/ + category: security + technology: + - python + confidence: MEDIUM + subcategory: + - vuln + likelihood: MEDIUM + impact: HIGH + severity: WARNING + languages: + - python +- id: python.lang.security.audit.dangerous-subprocess-use-audit.dangerous-subprocess-use-audit + pattern-either: + - patterns: + - pattern-not: subprocess.$FUNC("...", ...) + - pattern-not: subprocess.$FUNC(["...",...], ...) + - pattern-not: subprocess.$FUNC(("...",...), ...) + - pattern-not: + patterns: + - pattern-not-inside: | # Double negative, so this creates findings when a shell array is present + $ARR = ["=~/(sh|bash|ksh|csh|tcsh|zsh)/", "-c", ...] + ... + - pattern-inside: | # Filter out safe non-shell arrays + $ARR = [...] + ... + - pattern-either: + - pattern: subprocess.$FUNC(*$ARR, ...) + - pattern: subprocess.$FUNC([*$ARR, ...]) + - pattern-not: subprocess.CalledProcessError(...) + - pattern-not: subprocess.SubprocessError(...) + - pattern: subprocess.$FUNC(...) + - patterns: + - pattern: subprocess.$FUNC("=~/(sh|bash|ksh|csh|tcsh|zsh)/","-c",...) + - pattern-not: subprocess.$FUNC("=~/(sh|bash|ksh|csh|tcsh|zsh)/","-c","...",...) + - patterns: + - pattern-either: + - pattern: subprocess.$FUNC(["=~/(sh|bash|ksh|csh|tcsh|zsh)/","-c",...],...) + - pattern: subprocess.$FUNC(("=~/(sh|bash|ksh|csh|tcsh|zsh)/","-c",...),...) + - pattern-not: subprocess.$FUNC(["=~/(sh|bash|ksh|csh|tcsh|zsh)/","-c","...",...],...) + - pattern-not: subprocess.$FUNC(("=~/(sh|bash|ksh|csh|tcsh|zsh)/","-c","...",...),...) + - patterns: + - pattern: subprocess.$FUNC("=~/(python)/",...) + - pattern-not: subprocess.$FUNC("=~/(python)/","...",...) + - patterns: + - pattern-either: + - pattern: subprocess.$FUNC(["=~/(python)/",...],...) + - pattern: subprocess.$FUNC(("=~/(python)/",...),...) + - pattern-not: subprocess.$FUNC(["=~/(python)/","...",...],...) + - pattern-not: subprocess.$FUNC(("=~/(python)/","...",...),...) + message: >- + Detected subprocess function '$FUNC' without a static string. If this data can + be + controlled by a malicious actor, it may be an instance of command injection. + Audit the use of this call to ensure it is not controllable by an external resource. + You may consider using 'shlex.escape()'. + metadata: + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + cwe: + - "CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')" + asvs: + section: 'V5: Validation, Sanitization and Encoding Verification Requirements' + control_id: 5.3.8 OS Command Injection + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x13-V5-Validation-Sanitization-Encoding.md#v53-output-encoding-and-injection-prevention-requirements + version: '4' + references: + - https://stackoverflow.com/questions/3172470/actual-meaning-of-shell-true-in-subprocess + - https://docs.python.org/3/library/subprocess.html + - https://docs.python.org/3/library/shlex.html + - https://semgrep.dev/docs/cheat-sheets/python-command-injection/ + category: security + technology: + - python + confidence: LOW + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH + languages: [python] + severity: ERROR + +- id: python.lang.security.audit.dangerous-subprocess-use-tainted-env-args.dangerous-subprocess-use-tainted-env-args + mode: taint + options: + symbolic_propagation: true + pattern-sources: + - patterns: + - pattern-either: + - patterns: + - pattern-either: + - pattern: os.environ + - pattern: os.environ.get('$FOO', ...) + - pattern: os.environb + - pattern: os.environb.get('$FOO', ...) + - pattern: os.getenv('$ANYTHING', ...) + - pattern: os.getenvb('$ANYTHING', ...) + - patterns: + - pattern-either: + - patterns: + - pattern-either: + - pattern: sys.argv + - pattern: sys.orig_argv + - patterns: + - pattern-inside: | + $PARSER = argparse.ArgumentParser(...) + ... + - pattern-inside: | + $ARGS = $PARSER.parse_args() + - pattern: <... $ARGS ...> + - patterns: + - pattern-inside: | + $PARSER = optparse.OptionParser(...) + ... + - pattern-inside: | + $ARGS = $PARSER.parse_args() + - pattern: <... $ARGS ...> + - patterns: + - pattern-either: + - pattern-inside: | + $OPTS, $ARGS = getopt.getopt(...) + ... + - pattern-inside: | + $OPTS, $ARGS = getopt.gnu_getopt(...) + ... + - pattern-either: + - patterns: + - pattern-inside: | + for $O, $A in $OPTS: + ... + - pattern: $A + - pattern: $ARGS + pattern-sinks: + - patterns: + - pattern-either: + - patterns: + - pattern-not: subprocess.$FUNC("...", ...) + - pattern-not: subprocess.$FUNC(["...",...], ...) + - pattern-not: subprocess.$FUNC(("...",...), ...) + - pattern-not: subprocess.CalledProcessError(...) + - pattern-not: subprocess.SubprocessError(...) + - pattern: subprocess.$FUNC($CMD, ...) + - patterns: + - pattern-not: subprocess.$FUNC("=~/(sh|bash|ksh|csh|tcsh|zsh)/","-c","...",...) + - pattern: subprocess.$FUNC("=~/(sh|bash|ksh|csh|tcsh|zsh)/","-c", $CMD) + - patterns: + - pattern-not: subprocess.$FUNC(["=~/(sh|bash|ksh|csh|tcsh|zsh)/","-c","...",...],...) + - pattern-not: subprocess.$FUNC(("=~/(sh|bash|ksh|csh|tcsh|zsh)/","-c","...",...),...) + - pattern-either: + - pattern: subprocess.$FUNC(["=~/(sh|bash|ksh|csh|tcsh|zsh)/","-c", $CMD], ...) + - pattern: subprocess.$FUNC(("=~/(sh|bash|ksh|csh|tcsh|zsh)/","-c", $CMD), ...) + - patterns: + - pattern-not: subprocess.$FUNC("=~/(python)/","...",...) + - pattern: subprocess.$FUNC("=~/(python)/", $CMD) + - patterns: + - pattern-not: subprocess.$FUNC(["=~/(python)/","...",...],...) + - pattern-not: subprocess.$FUNC(("=~/(python)/","...",...),...) + - pattern-either: + - pattern: subprocess.$FUNC(["=~/(python)/", $CMD],...) + - pattern: subprocess.$FUNC(("=~/(python)/", $CMD),...) + - focus-metavariable: $CMD + message: >- + Detected subprocess function '$FUNC' with user controlled data. A malicious actor + could leverage this to perform command injection. + You may consider using 'shlex.escape()'. + metadata: + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + cwe: + - "CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')" + asvs: + section: 'V5: Validation, Sanitization and Encoding Verification Requirements' + control_id: 5.3.8 OS Command Injection + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x13-V5-Validation-Sanitization-Encoding.md#v53-output-encoding-and-injection-prevention-requirements + version: '4' + references: + - https://stackoverflow.com/questions/3172470/actual-meaning-of-shell-true-in-subprocess + - https://docs.python.org/3/library/subprocess.html + - https://docs.python.org/3/library/shlex.html + - https://semgrep.dev/docs/cheat-sheets/python-command-injection/ + category: security + technology: + - python + confidence: MEDIUM + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + languages: [python] + severity: ERROR +- id: python.lang.security.audit.dangerous-system-call-audit.dangerous-system-call-audit + patterns: + - pattern-not: os.$W("...", ...) + - pattern-either: + - pattern: os.system(...) + - pattern: getattr(os, "system")(...) + - pattern: __import__("os").system(...) + - pattern: getattr(__import__("os"), "system")(...) + - pattern: | + $X = __import__("os") + ... + $X.system(...) + - pattern: | + $X = __import__("os") + ... + getattr($X, "system")(...) + - pattern: | + $X = getattr(os, "system") + ... + $X(...) + - pattern: | + $X = __import__("os") + ... + $Y = getattr($X, "system") + ... + $Y(...) + - pattern: os.popen(...) + - pattern: os.popen2(...) + - pattern: os.popen3(...) + - pattern: os.popen4(...) + message: >- + Found dynamic content used in a system call. This is dangerous if external + data can reach this function call because it allows a malicious actor to + execute commands. Use the 'subprocess' module instead, which is easier + to use without accidentally exposing a command injection vulnerability. + metadata: + source-rule-url: https://bandit.readthedocs.io/en/latest/plugins/b605_start_process_with_a_shell.html + cwe: + - "CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')" + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + references: + - https://semgrep.dev/docs/cheat-sheets/python-command-injection/ + asvs: + section: 'V5: Validation, Sanitization and Encoding Verification Requirements' + control_id: 5.2.4 Dyanmic Code Execution Features + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x13-V5-Validation-Sanitization-Encoding.md#v52-sanitization-and-sandboxing-requirements + version: '4' + category: security + technology: + - python + confidence: LOW + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH + languages: [python] + severity: ERROR +- id: python.lang.security.audit.dangerous-system-call-tainted-env-args.dangerous-system-call-tainted-env-args + mode: taint + options: + symbolic_propagation: true + pattern-sources: + - patterns: + - pattern-either: + - patterns: + - pattern-either: + - pattern: os.environ + - pattern: os.environ.get('$FOO', ...) + - pattern: os.environb + - pattern: os.environb.get('$FOO', ...) + - pattern: os.getenv('$ANYTHING', ...) + - pattern: os.getenvb('$ANYTHING', ...) + - patterns: + - pattern-either: + - patterns: + - pattern-either: + - pattern: sys.argv + - pattern: sys.orig_argv + - patterns: + - pattern-inside: | + $PARSER = argparse.ArgumentParser(...) + ... + - pattern-inside: | + $ARGS = $PARSER.parse_args() + - pattern: <... $ARGS ...> + - patterns: + - pattern-inside: | + $PARSER = optparse.OptionParser(...) + ... + - pattern-inside: | + $ARGS = $PARSER.parse_args() + - pattern: <... $ARGS ...> + - patterns: + - pattern-either: + - pattern-inside: | + $OPTS, $ARGS = getopt.getopt(...) + ... + - pattern-inside: | + $OPTS, $ARGS = getopt.gnu_getopt(...) + ... + - pattern-either: + - patterns: + - pattern-inside: | + for $O, $A in $OPTS: + ... + - pattern: $A + - pattern: $ARGS + pattern-sinks: + - patterns: + - pattern-not: os.$W("...", ...) + - pattern-either: + - pattern: os.system(...) + - pattern: | + $X = __import__("os") + ... + $X.system(...) + - pattern: | + $X = __import__("os") + ... + getattr($X, "system")(...) + - pattern: | + $X = getattr(os, "system") + ... + $X(...) + - pattern: | + $X = __import__("os") + ... + $Y = getattr($X, "system") + ... + $Y(...) + - pattern: os.popen(...) + - pattern: os.popen2(...) + - pattern: os.popen3(...) + - pattern: os.popen4(...) + message: >- + Found user-controlled data used in a system call. This could allow a + malicious actor to execute commands. Use the 'subprocess' module instead, + which is easier to use without accidentally exposing a command injection + vulnerability. + metadata: + source-rule-url: https://bandit.readthedocs.io/en/latest/plugins/b605_start_process_with_a_shell.html + cwe: + - "CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')" + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + references: + - https://semgrep.dev/docs/cheat-sheets/python-command-injection/ + asvs: + section: 'V5: Validation, Sanitization and Encoding Verification Requirements' + control_id: 5.2.4 Dyanmic Code Execution Features + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x13-V5-Validation-Sanitization-Encoding.md#v52-sanitization-and-sandboxing-requirements + version: '4' + category: security + technology: + - python + confidence: MEDIUM + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: HIGH + languages: [python] + severity: ERROR +- id: python.lang.security.audit.dangerous-testcapi-run-in-subinterp-audit.dangerous-testcapi-run-in-subinterp-audit + patterns: + - pattern-either: + - pattern: | + _testcapi.run_in_subinterp($PAYLOAD, ...) + - pattern: | + test.support.run_in_subinterp($PAYLOAD, ...) + - pattern-not: | + _testcapi.run_in_subinterp("...", ...) + - pattern-not: | + test.support.run_in_subinterp("...", ...) + message: >- + Found dynamic content in `run_in_subinterp`. + This is dangerous if external data can reach this function call because it allows + a malicious actor to run arbitrary Python code. + Ensure no external data reaches here. + metadata: + cwe: + - "CWE-95: Improper Neutralization of Directives in Dynamically Evaluated Code ('Eval Injection')" + owasp: + - A03:2021 - Injection + references: + - https://semgrep.dev/docs/cheat-sheets/python-command-injection/ + category: security + technology: + - python + confidence: LOW + subcategory: + - audit + likelihood: LOW + impact: HIGH + severity: WARNING + languages: + - python +- id: python.lang.security.audit.dangerous-testcapi-run-in-subinterp-tainted-env-args.dangerous-testcapi-run-in-subinterp-tainted-env-args + mode: taint + options: + symbolic_propagation: true + pattern-sources: + - patterns: + - pattern-either: + - patterns: + - pattern-either: + - pattern: os.environ + - pattern: os.environ.get('$FOO', ...) + - pattern: os.environb + - pattern: os.environb.get('$FOO', ...) + - pattern: os.getenv('$ANYTHING', ...) + - pattern: os.getenvb('$ANYTHING', ...) + - patterns: + - pattern-either: + - patterns: + - pattern-either: + - pattern: sys.argv + - pattern: sys.orig_argv + - patterns: + - pattern-inside: | + $PARSER = argparse.ArgumentParser(...) + ... + - pattern-inside: | + $ARGS = $PARSER.parse_args() + - pattern: <... $ARGS ...> + - patterns: + - pattern-inside: | + $PARSER = optparse.OptionParser(...) + ... + - pattern-inside: | + $ARGS = $PARSER.parse_args() + - pattern: <... $ARGS ...> + - patterns: + - pattern-either: + - pattern-inside: | + $OPTS, $ARGS = getopt.getopt(...) + ... + - pattern-inside: | + $OPTS, $ARGS = getopt.gnu_getopt(...) + ... + - pattern-either: + - patterns: + - pattern-inside: | + for $O, $A in $OPTS: + ... + - pattern: $A + - pattern: $ARGS + pattern-sinks: + - patterns: + - pattern-either: + - pattern-inside: | + _testcapi.run_in_subinterp($PAYLOAD, ...) + - pattern-inside: | + test.support.run_in_subinterp($PAYLOAD, ...) + - pattern: $PAYLOAD + - pattern-not: | + _testcapi.run_in_subinterp("...", ...) + - pattern-not: | + test.support.run_in_subinterp("...", ...) + message: >- + Found user controlled content in `run_in_subinterp`. + This is dangerous because it allows a malicious actor to run arbitrary Python code. + metadata: + cwe: + - "CWE-95: Improper Neutralization of Directives in Dynamically Evaluated Code ('Eval Injection')" + owasp: + - A03:2021 - Injection + references: + - https://semgrep.dev/docs/cheat-sheets/python-command-injection/ + category: security + technology: + - python + confidence: MEDIUM + subcategory: + - vuln + likelihood: MEDIUM + impact: HIGH + severity: WARNING + languages: + - python +- id: python.lang.security.audit.dynamic-urllib-use-detected.dynamic-urllib-use-detected + patterns: + - pattern-not: urllib.$W("...") + - pattern-not: urllib.request.$W("...") + - pattern-not: $OPENER.$W("...") + - pattern-either: + - pattern: urllib.urlopen(...) + - pattern: urllib.request.urlopen(...) + - pattern: urllib.urlretrieve(...) + - pattern: urllib.request.urlretrieve(...) + - patterns: + - pattern-either: + - pattern-inside: | + $OPENER = urllib.URLopener(...) + ... + - pattern-inside: | + $OPENER = urllib.request.URLopener(...) + ... + - pattern-inside: | + $OPENER = urllib.FancyURLopener(...) + ... + - pattern-inside: | + $OPENER = urllib.request.FancyURLopener(...) + ... + - pattern-either: + - pattern: $OPENER.open(...) + - pattern: $OPENER.retrieve(...) + message: >- + Detected a dynamic value being used with urllib. urllib supports 'file://' schemes, + so a dynamic value controlled by a malicious actor may allow them to read arbitrary + files. + Audit uses of urllib calls to ensure user data cannot control the URLs, or consider + using the 'requests' library instead. + metadata: + cwe: + - 'CWE-939: Improper Authorization in Handler for Custom URL Scheme' + owasp: 'A01:2017 - Injection' + source-rule-url: https://github.com/PyCQA/bandit/blob/b1411bfb43795d3ffd268bef17a839dee954c2b1/bandit/blacklists/calls.py#L163 + bandit-code: B310 + asvs: + section: 'V5: Validation, Sanitization and Encoding Verification Requirements' + control_id: 5.2.4 Dynamic Code Execution Features + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x13-V5-Validation-Sanitization-Encoding.md#v52-sanitization-and-sandboxing-requirements + version: '4' + category: security + technology: + - python + references: + - https://cwe.mitre.org/data/definitions/939.html + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [python] + severity: WARNING +- id: python.lang.security.audit.eval-detected.eval-detected + patterns: + - pattern-not: eval(f"") + - pattern-not: eval("...") + - pattern: eval(...) + message: >- + Detected the use of eval(). eval() can be dangerous if used to evaluate + dynamic content. If this content can be input from outside the program, this + may be a code injection vulnerability. Ensure evaluated content is not definable + by external sources. + metadata: + source-rule-url: https://bandit.readthedocs.io/en/latest/blacklists/blacklist_calls.html#b307-eval + cwe: + - "CWE-95: Improper Neutralization of Directives in Dynamically Evaluated Code ('Eval Injection')" + owasp: + - A03:2021 - Injection + asvs: + section: 'V5: Validation, Sanitization and Encoding Verification Requirements' + control_id: 5.2.4 Dyanmic Code Execution Features + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x13-V5-Validation-Sanitization-Encoding.md#v52-sanitization-and-sandboxing-requirements + version: '4' + category: security + technology: + - python + references: + - https://owasp.org/Top10/A03_2021-Injection + subcategory: + - audit + likelihood: LOW + impact: HIGH + confidence: LOW + languages: [python] + severity: WARNING +- id: python.lang.security.audit.exec-detected.exec-detected + patterns: + - pattern-not: exec("...") + - pattern: exec(...) + message: >- + Detected the use of exec(). exec() can be dangerous if used to evaluate + dynamic content. If this content can be input from outside the program, this + may be a code injection vulnerability. Ensure evaluated content is not definable + by external sources. + metadata: + source-rule-url: https://bandit.readthedocs.io/en/latest/plugins/b102_exec_used.html + cwe: + - "CWE-95: Improper Neutralization of Directives in Dynamically Evaluated Code ('Eval Injection')" + owasp: + - A03:2021 - Injection + asvs: + section: 'V5: Validation, Sanitization and Encoding Verification Requirements' + control_id: 5.2.4 Dyanmic Code Execution Features + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x13-V5-Validation-Sanitization-Encoding.md#v52-sanitization-and-sandboxing-requirements + version: '4' + category: security + technology: + - python + references: + - https://owasp.org/Top10/A03_2021-Injection + subcategory: + - audit + likelihood: LOW + impact: HIGH + confidence: LOW + languages: [python] + severity: WARNING +- id: python.lang.security.audit.formatted-sql-query.formatted-sql-query + message: >- + Detected possible formatted SQL query. Use parameterized queries instead. + metadata: + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + cwe: + - "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')" + references: + - https://stackoverflow.com/questions/775296/mysql-parameterized-queries + category: security + technology: + - python + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH + confidence: LOW + severity: WARNING + languages: + - python + pattern-either: + - pattern: $DB.execute("..." % ...) + - pattern: $DB.execute("...".format(...)) + - pattern: $DB.execute(f"...") + - patterns: + - pattern-either: + - pattern-inside: | + $SQL = "..." % ... + ... + - pattern-inside: | + $SQL = "...".format(...) + ... + - pattern-inside: | + $SQL = f"...{$X}..." + ... + - pattern: $DB.execute($SQL) +- id: python.lang.security.audit.ftplib.ftplib + pattern: ftplib.$ANYTHING(...) + message: >- + FTP does not encrypt communications by default. This can lead to sensitive + data being exposed. Ensure use of FTP here does not expose sensitive data. + metadata: + source-rule-url: https://github.com/PyCQA/bandit/blob/d5f8fa0d89d7b11442fc6ec80ca42953974354c8/bandit/blacklists/calls.py#L265 + cwe: + - 'CWE-319: Cleartext Transmission of Sensitive Information' + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + bandit-code: B321 + references: + - https://docs.python.org/3/library/telnetlib.html + category: security + technology: + - ftplib + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + severity: WARNING + languages: + - python +- id: python.lang.security.audit.hardcoded-password-default-argument.hardcoded-password-default-argument + message: >- + Hardcoded password is used as a default argument to '$FUNC'. This could be dangerous + if + a real password is not supplied. + languages: [python] + severity: WARNING + patterns: + - pattern: | + def $FUNC(..., password="...", ...): + ... + - pattern-not: | + def $FUNC(..., password="", ...): + ... + metadata: + cwe: + - 'CWE-798: Use of Hard-coded Credentials' + category: security + technology: + - python + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW +- id: python.lang.security.audit.httpsconnection-detected.httpsconnection-detected + message: >- + The HTTPSConnection API has changed frequently with minor releases of Python. + Ensure you are using the API for your version of Python securely. + For example, Python 3 versions prior to 3.4.3 will not verify SSL certificates + by default. + See https://docs.python.org/3/library/http.client.html#http.client.HTTPSConnection + for more information. + metadata: + owasp: + - A03:2017 - Sensitive Data Exposure + - A07:2021 - Identification and Authentication Failures + cwe: + - 'CWE-295: Improper Certificate Validation' + references: + - https://docs.python.org/3/library/http.client.html#http.client.HTTPSConnection + category: security + technology: + - python + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + severity: WARNING + languages: + - python + pattern-either: + - pattern: httplib.HTTPSConnection(...) + - pattern: http.client.HTTPSConnection(...) + - pattern: six.moves.http_client.HTTPSConnection(...) +- id: python.lang.security.audit.insecure-file-permissions.insecure-file-permissions + languages: [python] + severity: WARNING + metadata: + category: security + owasp: + - A01:2021 - Broken Access Control + cwe: + - 'CWE-276: Incorrect Default Permissions' + technology: + - python + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: LOW + impact: MEDIUM + confidence: MEDIUM + message: >- + These permissions `$BITS` are widely permissive and grant access + to more people than may be necessary. A good default is `0o644` which + gives read and write access to yourself and read access to everyone else. + patterns: + - pattern-inside: os.$METHOD(...) + - metavariable-pattern: + metavariable: $METHOD + patterns: + - pattern-either: + - pattern: chmod + - pattern: lchmod + - pattern: fchmod + - pattern-either: + - patterns: + - pattern: os.$METHOD($FILE, $BITS, ...) + - metavariable-comparison: + metavariable: $BITS + comparison: $BITS >= 0o650 and $BITS < 0o100000 + - patterns: + - pattern: os.$METHOD($FILE, $BITS) + - metavariable-comparison: + metavariable: $BITS + comparison: $BITS >= 0o100650 + - patterns: + - pattern: os.$METHOD($FILE, $BITS, ...) + - metavariable-pattern: + metavariable: $BITS + patterns: + - pattern-either: + - pattern: <... stat.S_IWGRP ...> + - pattern: <... stat.S_IXGRP ...> + - pattern: <... stat.S_IWOTH ...> + - pattern: <... stat.S_IXOTH ...> + - pattern: <... stat.S_IRWXO ...> + - pattern: <... stat.S_IRWXG ...> + - patterns: + - pattern: os.$METHOD($FILE, $EXPR | $MOD, ...) + - metavariable-comparison: + metavariable: $MOD + comparison: $MOD == 0o111 +- id: python.lang.security.audit.insecure-transport.ftplib.use-ftp-tls.use-ftp-tls + pattern: ftplib.FTP(...) + fix-regex: + regex: FTP(.*)\) + replacement: FTP_TLS\1, context=ssl.create_default_context()) + message: >- + The 'FTP' class sends information unencrypted. Consider using + the 'FTP_TLS' class instead. + metadata: + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + cwe: + - 'CWE-319: Cleartext Transmission of Sensitive Information' + references: + - https://docs.python.org/3/library/ftplib.html#ftplib.FTP_TLS + category: security + technology: + - ftplib + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + severity: WARNING + languages: [python] +- id: python.lang.security.audit.insecure-transport.requests.request-session-http-in-with-context.request-session-http-in-with-context + options: + symbolic_propagation: true + mode: taint + pattern-sources: + - patterns: + - pattern: | + "$URL" + - metavariable-pattern: + metavariable: $URL + language: regex + patterns: + - pattern-regex: http:// + - pattern-not-regex: >- + .*://localhost + - pattern-not-regex: >- + .*://127\.0\.0\.1 + pattern-sinks: + - patterns: + - pattern-inside: | + with requests.Session(...) as $SESSION: + ... + - pattern-either: + - pattern: $SESSION.$W($SINK, ...) + - pattern: $SESSION.request($METHOD, $SINK, ...) + - focus-metavariable: $SINK + fix-regex: + regex: '[Hh][Tt][Tt][Pp]://' + replacement: https:// + count: 1 + message: >- + Detected a request using 'http://'. This request will be unencrypted. Use 'https://' + instead. + metadata: + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + cwe: + - 'CWE-319: Cleartext Transmission of Sensitive Information' + asvs: + section: V9 Communications Verification Requirements + control_id: 9.2.1 Weak TLS + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x17-V9-Communications.md#v92-server-communications-security-requirements + version: '4' + category: security + technology: + - requests + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: MEDIUM + languages: [python] + severity: INFO +- id: python.lang.security.audit.insecure-transport.requests.request-session-with-http.request-session-with-http + options: + symbolic_propagation: true + mode: taint + pattern-sources: + - patterns: + - pattern: | + "$URL" + - metavariable-pattern: + metavariable: $URL + language: regex + patterns: + - pattern-regex: http:// + - pattern-not-regex: >- + .*://localhost + - pattern-not-regex: >- + .*://127\.0\.0\.1 + pattern-sinks: + - patterns: + - pattern-either: + - pattern: requests.Session(...).$W($SINK, ...) + - pattern: requests.Session(...).request($METHOD, $SINK, ...) + - focus-metavariable: $SINK + fix-regex: + regex: "[Hh][Tt][Tt][Pp]://" + replacement: https:// + count: 1 + message: Detected a request using 'http://'. This request will be unencrypted. + Use 'https://' instead. + languages: + - python + severity: INFO + metadata: + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + cwe: + - 'CWE-319: Cleartext Transmission of Sensitive Information' + asvs: + section: V9 Communications Verification Requirements + control_id: 9.1.1 Weak TLS + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x17-V9-Communications.md#v92-server-communications-security-requirements + version: '4' + category: security + technology: + - requests + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: MEDIUM + +- id: python.lang.security.audit.insecure-transport.requests.request-with-http.request-with-http + fix-regex: + regex: '[Hh][Tt][Tt][Pp]://' + replacement: https:// + count: 1 + message: >- + Detected a request using 'http://'. This request will be unencrypted, + and attackers could listen into traffic on the network and be able + to obtain sensitive information. Use 'https://' instead. + metadata: + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + cwe: + - 'CWE-319: Cleartext Transmission of Sensitive Information' + asvs: + section: V9 Communications Verification Requirements + control_id: 9.1.1 Weak TLS + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x17-V9-Communications.md#v92-server-communications-security-requirements + version: '4' + category: security + technology: + - requests + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: MEDIUM + languages: [python] + severity: INFO + options: + symbolic_propagation: true + mode: taint + pattern-sources: + - patterns: + - pattern: | + "$URL" + - metavariable-pattern: + metavariable: $URL + language: regex + patterns: + - pattern-regex: http:// + - pattern-not-regex: >- + .*://localhost + - pattern-not-regex: >- + .*://127\.0\.0\.1 + pattern-sinks: + - patterns: + - pattern-either: + - pattern: requests.$W($SINK, ...) + - pattern: requests.request($METHOD, $SINK, ...) + - pattern: requests.Request($METHOD, $SINK, ...) + - focus-metavariable: $SINK +- id: python.lang.security.audit.insecure-transport.ssl.no-set-ciphers.no-set-ciphers + pattern: $CONTEXT.set_ciphers(...) + message: >- + The 'ssl' module disables insecure cipher suites by default. Therefore, + use of 'set_ciphers()' should only be used when you have very specialized + requirements. Otherwise, you risk lowering the security of the SSL channel. + metadata: + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + cwe: + - 'CWE-326: Inadequate Encryption Strength' + asvs: + section: V9 Communications Verification Requirements + control_id: 9.1.3 Weak TLS + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x17-V9-Communications.md#v91-client-communications-security-requirements + version: '4' + references: + - https://docs.python.org/3/library/ssl.html#cipher-selection + - https://docs.python.org/3/library/ssl.html#ssl.SSLContext.set_ciphers + category: security + technology: + - ssl + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [python] + severity: WARNING +- id: python.lang.security.audit.insecure-transport.urllib.insecure-openerdirector-open-ftp.insecure-openerdirector-open-ftp + message: >- + Detected an unsecured transmission channel. 'OpenerDirector.open(...)' is + being used with 'ftp://'. Information sent over this connection will be + unencrypted. Consider using SFTP instead. urllib does not support SFTP, + so consider a library which supports SFTP. + metadata: + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + cwe: + - 'CWE-319: Cleartext Transmission of Sensitive Information' + references: + - https://docs.python.org/3/library/urllib.request.html#urllib.request.OpenerDirector.open + category: security + technology: + - urllib + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + severity: WARNING + languages: [python] + pattern-either: + - pattern: urllib.request.OpenerDirector(...).open("=~/^[Ff][Tt][Pp]://.*/", ...) + - patterns: + - pattern-inside: | + $OPENERDIRECTOR = urllib.request.OpenerDirector(...) + ... + - pattern: $OPENERDIRECTOR.open("=~/^[Ff][Tt][Pp]://.*/", ...) + - patterns: + - pattern-inside: | + $OPENERDIRECTOR = urllib.request.OpenerDirector(...) + ... + - pattern: | + $URL = "=~/^[Ff][Tt][Pp]://.*/" + ... + $OPENERDIRECTOR.open($URL, ...) + - pattern: | + $URL = "=~/^[Ff][Tt][Pp]://.*/" + ... + urllib.request.OpenerDirector(...).open($URL, ...) + - patterns: + - pattern-inside: | + def $FUNC(..., $URL = "=~/^[Ff][Tt][Pp]://.*/", ...): + ... + - pattern-either: + - pattern: urllib.request.OpenerDirector(...).open($URL, ...) + - patterns: + - pattern-inside: | + $OPENERDIRECTOR = urllib.request.OpenerDirector(...) + ... + - pattern: $OPENERDIRECTOR.open($URL, ...) +- id: python.lang.security.audit.insecure-transport.urllib.insecure-openerdirector-open.insecure-openerdirector-open + message: >- + Detected an unsecured transmission channel. 'OpenerDirector.open(...)' is + being used with 'http://'. Use 'https://' instead to secure the channel. + metadata: + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + cwe: + - 'CWE-319: Cleartext Transmission of Sensitive Information' + references: + - https://docs.python.org/3/library/urllib.request.html#urllib.request.OpenerDirector.open + category: security + technology: + - urllib + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + severity: WARNING + languages: [python] + fix-regex: + regex: '[Hh][Tt][Tt][Pp]://' + replacement: https:// + count: 1 + pattern-either: + - pattern: urllib.request.OpenerDirector(...).open("=~/[Hh][Tt][Tt][Pp]://.*/", ...) + - patterns: + - pattern-inside: | + $OPENERDIRECTOR = urllib.request.OpenerDirector(...) + ... + - pattern: $OPENERDIRECTOR.open("=~/[Hh][Tt][Tt][Pp]://.*/", ...) + - patterns: + - pattern-inside: | + $OPENERDIRECTOR = urllib.request.OpenerDirector(...) + ... + - pattern: | + $URL = "=~/[Hh][Tt][Tt][Pp]://.*/" + ... + $OPENERDIRECTOR.open($URL, ...) + - pattern: | + $URL = "=~/[Hh][Tt][Tt][Pp]://.*/" + ... + urllib.request.OpenerDirector(...).open($URL, ...) + - patterns: + - pattern-inside: | + def $FUNC(..., $URL = "=~/[Hh][Tt][Tt][Pp]://.*/", ...): + ... + - pattern-either: + - pattern: urllib.request.OpenerDirector(...).open($URL, ...) + - patterns: + - pattern-inside: | + $OPENERDIRECTOR = urllib.request.OpenerDirector(...) + ... + - pattern: $OPENERDIRECTOR.open($URL, ...) +- id: python.lang.security.audit.insecure-transport.urllib.insecure-request-object-ftp.insecure-request-object-ftp + message: >- + Detected a 'urllib.request.Request()' object using an insecure transport + protocol, 'ftp://'. This connection will not be encrypted. Consider using + SFTP instead. urllib does not support SFTP natively, so consider using + a library which supports SFTP. + metadata: + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + cwe: + - 'CWE-319: Cleartext Transmission of Sensitive Information' + references: + - https://docs.python.org/3/library/urllib.request.html#urllib.request.Request + category: security + technology: + - urllib + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + severity: WARNING + languages: [python] + pattern-either: + - pattern: urllib.request.Request("=~/^[Ff][Tt][Pp]://.*/", ...) + - pattern: | + $URL = "=~/^[Ff][Tt][Pp]://.*/" + ... + urllib.request.Request($URL, ...) + - pattern: |- + def $FUNC(..., $URL = "=~/^[Ff][Tt][Pp]://.*/", ...): + ... + urllib.request.Request($URL, ...) +- id: python.lang.security.audit.insecure-transport.urllib.insecure-request-object.insecure-request-object + message: >- + Detected a 'urllib.request.Request()' object using an insecure transport + protocol, 'http://'. This connection will not be encrypted. Use + 'https://' instead. + metadata: + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + cwe: + - 'CWE-319: Cleartext Transmission of Sensitive Information' + references: + - https://docs.python.org/3/library/urllib.request.html#urllib.request.Request + category: security + technology: + - urllib + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + severity: WARNING + languages: [python] + fix-regex: + regex: '[Hh][Tt][Tt][Pp]://' + replacement: https:// + count: 1 + pattern-either: + - pattern: urllib.request.Request("=~/[Hh][Tt][Tt][Pp]://.*/", ...) + - pattern: | + $URL = "=~/[Hh][Tt][Tt][Pp]://.*/" + ... + urllib.request.Request($URL, ...) + - pattern: | + def $FUNC(..., $URL = "=~/[Hh][Tt][Tt][Pp]://.*/", ...): + ... + urllib.request.Request($URL, ...) +- id: python.lang.security.audit.insecure-transport.urllib.insecure-urlopen-ftp.insecure-urlopen-ftp + message: >- + Detected 'urllib.urlopen()' using 'ftp://'. This request will not be + encrypted. Consider using SFTP instead. urllib does not support SFTP, + so consider switching to a library which supports SFTP. + metadata: + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + cwe: + - 'CWE-319: Cleartext Transmission of Sensitive Information' + references: + - https://docs.python.org/3/library/urllib.request.html#urllib.request.urlopen + category: security + technology: + - urllib + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + severity: WARNING + languages: [python] + pattern-either: + - pattern: urllib.request.urlopen("=~/^[Ff][Tt][Pp]://.*/", ...) + - pattern: | + $URL = "=~/^[Ff][Tt][Pp]://.*/" + ... + urllib.request.urlopen($URL, ...) + - pattern: |- + def $FUNC(..., $URL = "=~/^[Ff][Tt][Pp]://.*/", ...): + ... + urllib.request.urlopen($URL, ...) +- id: python.lang.security.audit.insecure-transport.urllib.insecure-urlopen.insecure-urlopen + message: >- + Detected 'urllib.urlopen()' using 'http://'. This request will not be + encrypted. Use 'https://' instead. + metadata: + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + cwe: + - 'CWE-319: Cleartext Transmission of Sensitive Information' + references: + - https://docs.python.org/3/library/urllib.request.html#urllib.request.urlopen + category: security + technology: + - urllib + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + severity: WARNING + languages: [python] + fix-regex: + regex: '[Hh][Tt][Tt][Pp]://' + replacement: https:// + pattern-either: + - pattern: urllib.request.urlopen("=~/[Hh][Tt][Tt][Pp]://.*/", ...) + - pattern: | + $URL = "=~/[Hh][Tt][Tt][Pp]://.*/" + ... + urllib.request.urlopen($URL, ...) + - pattern: | + def $FUNC(..., $URL = "=~/[Hh][Tt][Tt][Pp]://.*/", ...): + ... + urllib.request.urlopen($URL, ...) +- id: python.lang.security.audit.insecure-transport.urllib.insecure-urlopener-open-ftp.insecure-urlopener-open-ftp + message: >- + Detected an insecure transmission channel. 'URLopener.open(...)' is + being used with 'ftp://'. Use SFTP instead. urllib does not support + SFTP, so consider using a library which supports SFTP. + metadata: + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + cwe: + - 'CWE-319: Cleartext Transmission of Sensitive Information' + references: + - https://docs.python.org/3/library/urllib.request.html#urllib.request.URLopener.open + category: security + technology: + - urllib + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + severity: WARNING + languages: [python] + pattern-either: + - pattern: urllib.request.URLopener(...).open("=~/[Ff][Tt][Pp]://.*/", ...) + - patterns: + - pattern-inside: | + $OPENERDIRECTOR = urllib.request.URLopener(...) + ... + - pattern: $OPENERDIRECTOR.open("=~/[Ff][Tt][Pp]://.*/", ...) + - patterns: + - pattern-inside: | + $OPENERDIRECTOR = urllib.request.URLopener(...) + ... + - pattern: | + $URL = "=~/[Ff][Tt][Pp]://.*/" + ... + $OPENERDIRECTOR.open($URL, ...) + - pattern: | + $URL = "=~/[Ff][Tt][Pp]://.*/" + ... + urllib.request.URLopener(...).open($URL, ...) + - patterns: + - pattern-inside: | + def $FUNC(..., $URL = "=~/[Ff][Tt][Pp]://.*/", ...): + ... + - pattern-either: + - pattern: urllib.request.URLopener(...).open($URL, ...) + - patterns: + - pattern-inside: | + $OPENERDIRECTOR = urllib.request.URLopener(...) + ... + - pattern: $OPENERDIRECTOR.open($URL, ...) +- id: python.lang.security.audit.insecure-transport.urllib.insecure-urlopener-open.insecure-urlopener-open + message: >- + Detected an unsecured transmission channel. 'URLopener.open(...)' is + being used with 'http://'. Use 'https://' instead to secure the channel. + metadata: + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + cwe: + - 'CWE-319: Cleartext Transmission of Sensitive Information' + references: + - https://docs.python.org/3/library/urllib.request.html#urllib.request.URLopener.open + category: security + technology: + - urllib + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + severity: WARNING + languages: [python] + fix-regex: + regex: '[Hh][Tt][Tt][Pp]://' + replacement: https:// + count: 1 + pattern-either: + - pattern: urllib.request.URLopener(...).open("=~/[Hh][Tt][Tt][Pp]://.*/", ...) + - patterns: + - pattern-inside: | + $OPENERDIRECTOR = urllib.request.URLopener(...) + ... + - pattern: $OPENERDIRECTOR.open("=~/[Hh][Tt][Tt][Pp]://.*/", ...) + - patterns: + - pattern-inside: | + $OPENERDIRECTOR = urllib.request.URLopener(...) + ... + - pattern: | + $URL = "=~/[Hh][Tt][Tt][Pp]://.*/" + ... + $OPENERDIRECTOR.open($URL, ...) + - pattern: | + $URL = "=~/[Hh][Tt][Tt][Pp]://.*/" + ... + urllib.request.URLopener(...).open($URL, ...) + - patterns: + - pattern-inside: | + def $FUNC(..., $URL = "=~/[Hh][Tt][Tt][Pp]://.*/", ...): + ... + - pattern-either: + - pattern: urllib.request.URLopener(...).open($URL, ...) + - patterns: + - pattern-inside: | + $OPENERDIRECTOR = urllib.request.URLopener(...) + ... + - pattern: $OPENERDIRECTOR.open($URL, ...) +- id: python.lang.security.audit.insecure-transport.urllib.insecure-urlopener-retrieve-ftp.insecure-urlopener-retrieve-ftp + message: >- + Detected an insecure transmission channel. 'URLopener.retrieve(...)' is + being used with 'ftp://'. Use SFTP instead. urllib does not support + SFTP, so consider using a library which supports SFTP. + metadata: + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + cwe: + - 'CWE-319: Cleartext Transmission of Sensitive Information' + references: + - https://docs.python.org/3/library/urllib.request.html#urllib.request.URLopener.retrieve + category: security + technology: + - urllib + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + severity: WARNING + languages: [python] + pattern-either: + - pattern: urllib.request.URLopener(...).retrieve("=~/[Ff][Tt][Pp]://.*/", ...) + - patterns: + - pattern-inside: | + $OPENERDIRECTOR = urllib.request.URLopener(...) + ... + - pattern: $OPENERDIRECTOR.retrieve("=~/[Ff][Tt][Pp]://.*/", ...) + - patterns: + - pattern-inside: | + $OPENERDIRECTOR = urllib.request.URLopener(...) + ... + - pattern: | + $URL = "=~/[Ff][Tt][Pp]://.*/" + ... + $OPENERDIRECTOR.retrieve($URL, ...) + - pattern: | + $URL = "=~/[Ff][Tt][Pp]://.*/" + ... + urllib.request.URLopener(...).retrieve($URL, ...) + - patterns: + - pattern-inside: | + def $FUNC(..., $URL = "=~/[Ff][Tt][Pp]://.*/", ...): + ... + - pattern-either: + - pattern: urllib.request.URLopener(...).retrieve($URL, ...) + - patterns: + - pattern-inside: | + $OPENERDIRECTOR = urllib.request.URLopener(...) + ... + - pattern: $OPENERDIRECTOR.retrieve($URL, ...) +- id: python.lang.security.audit.insecure-transport.urllib.insecure-urlopener-retrieve.insecure-urlopener-retrieve + message: >- + Detected an unsecured transmission channel. 'URLopener.retrieve(...)' is + being used with 'http://'. Use 'https://' instead to secure the channel. + metadata: + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + cwe: + - 'CWE-319: Cleartext Transmission of Sensitive Information' + references: + - https://docs.python.org/3/library/urllib.request.html#urllib.request.URLopener.retrieve + category: security + technology: + - urllib + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + severity: WARNING + languages: [python] + fix-regex: + regex: '[Hh][Tt][Tt][Pp]://' + replacement: https:// + count: 1 + pattern-either: + - pattern: urllib.request.URLopener(...).retrieve("=~/[Hh][Tt][Tt][Pp]://.*/", ...) + - patterns: + - pattern-inside: | + $OPENERDIRECTOR = urllib.request.URLopener(...) + ... + - pattern: $OPENERDIRECTOR.retrieve("=~/[Hh][Tt][Tt][Pp]://.*/", ...) + - patterns: + - pattern-inside: | + $OPENERDIRECTOR = urllib.request.URLopener(...) + ... + - pattern: | + $URL = "=~/[Hh][Tt][Tt][Pp]://.*/" + ... + $OPENERDIRECTOR.retrieve($URL, ...) + - pattern: | + $URL = "=~/[Hh][Tt][Tt][Pp]://.*/" + ... + urllib.request.URLopener(...).retrieve($URL, ...) + - patterns: + - pattern-inside: | + def $FUNC(..., $URL = "=~/[Hh][Tt][Tt][Pp]://.*/", ...): + ... + - pattern-either: + - pattern: urllib.request.URLopener(...).retrieve($URL, ...) + - patterns: + - pattern-inside: | + $OPENERDIRECTOR = urllib.request.URLopener(...) + ... + - pattern: $OPENERDIRECTOR.retrieve($URL, ...) +- id: python.lang.security.audit.insecure-transport.urllib.insecure-urlretrieve-ftp.insecure-urlretrieve-ftp + message: >- + Detected 'urllib.urlretrieve()' using 'ftp://'. This request will not be + encrypted. Use SFTP instead. urllib does not support SFTP, so consider + switching to a library which supports SFTP. + metadata: + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + cwe: + - 'CWE-319: Cleartext Transmission of Sensitive Information' + references: + - https://docs.python.org/3/library/urllib.request.html#urllib.request.urlretrieve + category: security + technology: + - urllib + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + severity: WARNING + languages: [python] + pattern-either: + - pattern: urllib.request.urlretrieve("=~/^[Ff][Tt][Pp]://.*/", ...) + - pattern: | + $URL = "=~/^[Ff][Tt][Pp]://.*/" + ... + urllib.request.urlretrieve($URL, ...) + - pattern: |- + def $FUNC(..., $URL = "=~/^[Ff][Tt][Pp]://.*/", ...): + ... + urllib.request.urlretrieve($URL, ...) +- id: python.lang.security.audit.insecure-transport.urllib.insecure-urlretrieve.insecure-urlretrieve + message: >- + Detected 'urllib.urlretrieve()' using 'http://'. This request will not be + encrypted. Use 'https://' instead. + metadata: + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + cwe: + - 'CWE-319: Cleartext Transmission of Sensitive Information' + references: + - https://docs.python.org/3/library/urllib.request.html#urllib.request.urlretrieve + category: security + technology: + - urllib + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + severity: WARNING + languages: [python] + fix-regex: + regex: '[Hh][Tt][Tt][Pp]://' + replacement: https:// + pattern-either: + - pattern: urllib.request.urlretrieve("=~/[Hh][Tt][Tt][Pp]://.*/", ...) + - pattern: | + $URL = "=~/[Hh][Tt][Tt][Pp]://.*/" + ... + urllib.request.urlretrieve($URL, ...) + - pattern: | + def $FUNC(..., $URL = "=~/[Hh][Tt][Tt][Pp]://.*/", ...): + ... + urllib.request.urlretrieve($URL, ...) +- id: python.lang.security.audit.logging.listeneval.listen-eval + languages: + - python + message: >- + Because portions of the logging configuration are passed through eval(), use of this function may + open its users to a + security risk. + While the function only binds to a socket on localhost, and so does not accept connections from remote + machines, + there are scenarios where untrusted code could be run under the account of the process which calls + listen(). + To avoid this happening, use the `verify()` argument to `listen()` to prevent unrecognized configurations. + metadata: + cwe: + - "CWE-95: Improper Neutralization of Directives in Dynamically Evaluated Code ('Eval Injection')" + owasp: + - A03:2021 - Injection + references: + - https://docs.python.org/3/library/logging.config.html?highlight=security#logging.config.listen + category: security + technology: + - python + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + severity: WARNING + pattern: logging.config.listen(...) +- id: python.lang.security.audit.logging.logger-credential-leak.python-logger-credential-disclosure + patterns: + - pattern: | + $LOGGER_OBJ.$LOGGER_CALL($FORMAT_STRING,...) + - metavariable-regex: + metavariable: $LOGGER_OBJ + regex: (?i)(_logger|logger|self.logger|log) + - metavariable-regex: + metavariable: $LOGGER_CALL + regex: (debug|info|warn|warning|error|exception|critical) + - metavariable-regex: + metavariable: $FORMAT_STRING + regex: (?i).*(api.key|secret|credential|token|password).*\%s.* + message: >- + Detected a python logger call with a potential hardcoded secret + $FORMAT_STRING being logged. This may lead to secret credentials + being exposed. Make sure that the logger is not logging + sensitive information. + severity: WARNING + languages: [python] + metadata: + cwe: + - 'CWE-532: Insertion of Sensitive Information into Log File' + category: security + technology: + - python + owasp: + - A09:2021 - Security Logging and Monitoring Failures + references: + - https://owasp.org/Top10/A09_2021-Security_Logging_and_Monitoring_Failures + subcategory: + - vuln + likelihood: LOW + impact: MEDIUM + confidence: MEDIUM +- id: python.lang.security.audit.mako-templates-detected.mako-templates-detected + pattern: mako.template.Template(...) + message: >- + Mako templates do not provide a global HTML escaping mechanism. + This means you must escape all sensitive data in your templates + using '| u' for URL escaping or '| h' for HTML escaping. + If you are using Mako to serve web content, consider using + a system such as Jinja2 which enables global escaping. + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + source-rule-url: https://github.com/PyCQA/bandit/blob/b1411bfb43795d3ffd268bef17a839dee954c2b1/bandit/plugins/mako_templates.py + references: + - https://docs.makotemplates.org/en/latest/syntax.html#expression-escaping + - https://jinja.palletsprojects.com/en/2.11.x/intro/# + category: security + technology: + - mako + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + languages: [python] + severity: INFO +- id: python.lang.security.audit.marshal.marshal-usage + languages: + - python + message: >- + The marshal module is not intended to be secure against erroneous or maliciously + constructed data. + Never unmarshal data received from an untrusted or unauthenticated source. + See more details: https://docs.python.org/3/library/marshal.html?highlight=security + metadata: + cwe: + - 'CWE-502: Deserialization of Untrusted Data' + owasp: + - A08:2017 - Insecure Deserialization + - A08:2021 - Software and Data Integrity Failures + references: + - https://docs.python.org/3/library/marshal.html?highlight=security + category: security + technology: + - python + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + pattern-either: + - pattern: marshal.dump(...) + - pattern: marshal.dumps(...) + - pattern: marshal.load(...) + - pattern: marshal.loads(...) + severity: WARNING +- id: python.lang.security.audit.md5-used-as-password.md5-used-as-password + severity: WARNING + message: >- + It looks like MD5 is used as a password hash. MD5 is not considered a + secure password hash because it can be cracked by an attacker in a short + amount of time. Use a suitable password hashing function such as scrypt. + You can use `hashlib.scrypt`. + languages: [python] + metadata: + cwe: + - 'CWE-327: Use of a Broken or Risky Cryptographic Algorithm' + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + references: + - https://tools.ietf.org/html/rfc6151 + - https://crypto.stackexchange.com/questions/44151/how-does-the-flame-malware-take-advantage-of-md5-collision + - https://pycryptodome.readthedocs.io/en/latest/src/hash/sha3_256.html + - https://security.stackexchange.com/questions/211/how-to-securely-hash-passwords + - https://github.com/returntocorp/semgrep-rules/issues/1609 + - https://docs.python.org/3/library/hashlib.html#hashlib.scrypt + category: security + technology: + - pycryptodome + - hashlib + - md5 + subcategory: + - vuln + likelihood: HIGH + impact: LOW + confidence: MEDIUM + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - pattern: hashlib.md5 + - pattern: hashlib.new(..., name="MD5", ...) + - pattern: Cryptodome.Hash.MD5 + - pattern: Crypto.Hash.MD5 + - pattern: cryptography.hazmat.primitives.hashes.MD5 + pattern-sinks: + - patterns: + - pattern: $FUNCTION(...) + - metavariable-regex: + metavariable: $FUNCTION + regex: (?i)(.*password.*) +- id: python.lang.security.audit.network.bind.avoid-bind-to-all-interfaces + message: >- + Running `socket.bind` to 0.0.0.0, or empty string could unexpectedly + expose the server publicly as it binds to all available interfaces. Consider + instead getting correct address from an environment variable or + configuration file. + metadata: + cwe: + - 'CWE-200: Exposure of Sensitive Information to an Unauthorized Actor' + owasp: + - A01:2021 - Broken Access Control + category: security + technology: + - python + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + cwe2021-top25: true + subcategory: + - vuln + likelihood: HIGH + impact: MEDIUM + confidence: HIGH + languages: [python] + severity: INFO + pattern-either: + - pattern: | + $S = socket.socket(...) + ... + $S.bind(("0.0.0.0", ...)) + - pattern: | + $S = socket.socket(...) + ... + $S.bind(("::", ...)) + - pattern: | + $S = socket.socket(...) + ... + $S.bind(("", ...)) +- id: python.lang.security.audit.network.disabled-cert-validation.disabled-cert-validation + patterns: + - pattern-either: + - pattern: urllib3.PoolManager(..., cert_reqs=$REQS, ...) + - pattern: urllib3.ProxyManager(..., cert_reqs=$REQS, ...) + - pattern: urllib3.HTTPSConnectionPool(..., cert_reqs=$REQS, ...) + - pattern: urllib3.connectionpool.HTTPSConnectionPool(..., cert_reqs=$REQS, ...) + - pattern: urllib3.connection_from_url(..., cert_reqs=$REQS, ...) + - pattern: urllib3.proxy_from_url(..., cert_reqs=$REQS, ...) + - pattern: $CONTEXT.wrap_socket(..., cert_reqs=$REQS, ...) + - pattern: ssl.wrap_socket(..., cert_reqs=$REQS, ...) + - metavariable-regex: + metavariable: $REQS + regex: (NONE|CERT_NONE|CERT_OPTIONAL|ssl\.CERT_NONE|ssl\.CERT_OPTIONAL|\'NONE\'|\"NONE\"|\'OPTIONAL\'|\"OPTIONAL\") + message: certificate verification explicitly disabled, insecure connections possible + metadata: + cwe: + - 'CWE-295: Improper Certificate Validation' + owasp: + - A03:2017 - Sensitive Data Exposure + - A07:2021 - Identification and Authentication Failures + category: security + technology: + - python + references: + - https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures + subcategory: + - vuln + likelihood: HIGH + impact: MEDIUM + confidence: MEDIUM + languages: [python] + severity: ERROR +- id: python.lang.security.audit.network.http-not-https-connection.http-not-https-connection + message: >- + Detected HTTPConnectionPool. This will transmit data in cleartext. + It is recommended to use HTTPSConnectionPool instead for to encrypt + communications. + metadata: + cwe: + - 'CWE-319: Cleartext Transmission of Sensitive Information' + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + references: + - https://urllib3.readthedocs.io/en/1.2.1/pools.html#urllib3.connectionpool.HTTPSConnectionPool + category: security + technology: + - python + subcategory: + - audit + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + languages: [python] + severity: ERROR + pattern-either: + - pattern: urllib3.HTTPConnectionPool(...) + - pattern: urllib3.connectionpool.HTTPConnectionPool(...) +- id: python.lang.security.audit.non-literal-import.non-literal-import + patterns: + - pattern: | + importlib.import_module($NAME, ...) + - pattern-not: | + importlib.import_module("...", ...) + message: >- + Untrusted user input in `importlib.import_module()` function allows an attacker + to load arbitrary code. + Avoid dynamic values in `importlib.import_module()` or use a whitelist to prevent + running untrusted code. + metadata: + owasp: + - A01:2021 - Broken Access Control + cwe: + - 'CWE-706: Use of Incorrectly-Resolved Name or Reference' + category: security + technology: + - python + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + languages: [python] + severity: WARNING +- id: python.lang.security.audit.paramiko-implicit-trust-host-key.paramiko-implicit-trust-host-key + patterns: + - pattern-inside: | + $CLIENT = paramiko.client.SSHClient(...) + ... + $CLIENT.set_missing_host_key_policy(...) + - pattern-either: + - pattern: paramiko.client.AutoAddPolicy + - pattern: paramiko.client.WarningPolicy + message: >- + Detected a paramiko host key policy that implicitly trusts a server's + host key. Host keys should be verified to ensure the connection + is not to a malicious server. Use RejectPolicy or a custom subclass + instead. + metadata: + cwe: + - 'CWE-322: Key Exchange without Entity Authentication' + owasp: + - A02:2021 - Cryptographic Failures + source-rule-url: https://github.com/PyCQA/bandit/blob/b1411bfb43795d3ffd268bef17a839dee954c2b1/bandit/plugins/ssh_no_host_key_verification.py + references: + - http://docs.paramiko.org/en/stable/api/client.html#paramiko.client.AutoAddPolicy + category: security + technology: + - paramiko + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + languages: [python] + severity: WARNING +- id: python.lang.security.audit.paramiko.paramiko-exec-command.paramiko-exec-command + patterns: + - pattern-inside: | + $CLIENT = paramiko.client.SSHClient(...) + ... + - pattern: $CLIENT.exec_command(...) + - pattern-not: $CLIENT.exec_command("...", ...) + message: >- + Unverified SSL context detected. This will permit insecure connections without + verifying + SSL certificates. Use 'ssl.create_default_context()' instead. + metadata: + source-rule-url: https://github.com/PyCQA/bandit/blob/d5f8fa0d89d7b11442fc6ec80ca42953974354c8/bandit/plugins/injection_paramiko.py + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + cwe: + - "CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')" + references: + - http://docs.paramiko.org/en/stable/api/client.html#paramiko.client.SSHClient.exec_command + - https://github.com/PyCQA/bandit/blob/d5f8fa0d89d7b11442fc6ec80ca42953974354c8/bandit/plugins/injection_paramiko.py + category: security + technology: + - paramiko + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH + confidence: LOW + severity: ERROR + languages: + - python +- id: python.lang.security.audit.python-reverse-shell.python-reverse-shell + patterns: + - pattern-either: + - pattern: pty.spawn("$BINPATH",...) + - pattern: subprocess.call(["$BINPATH",...],...) + - metavariable-regex: + metavariable: $BINPATH + regex: /bin/.*?sh\b + - pattern-inside: | + import socket + ... + $S = socket.socket(...) + ... + $S.connect(($IP,$PORT),...) + ... + message: Semgrep found a Python reverse shell using $BINPATH to $IP at $PORT + metadata: + cwe: + - 'CWE-553: Command Shell in Externally Accessible Directory' + category: security + technology: [python] + references: + - https://cwe.mitre.org/data/definitions/553.html + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + languages: + - python + severity: WARNING +- id: python.lang.security.audit.regex-dos.regex_dos + patterns: + - pattern: | + $A = re.compile("$B", ...) + ... + $A.$METHOD(...) + - metavariable-analysis: + analyzer: redos + metavariable: $B + - metavariable-regex: + metavariable: $METHOD + regex: (?!(escape)|(purge)) + message: >- + Detected usage of re.compile with an inefficient regular expression. + This can lead to regular expression denial of service, which can result + in service down time. Instead, check all regexes or use safer alternatives + such as pyre2. + languages: + - python + severity: WARNING + metadata: + likelihood: LOW + impact: MEDIUM + confidence: LOW + subcategory: + - vuln + owasp: 'A06:2017 - Security Misconfiguration' + cwe: 'CWE-1333: Inefficient Regular Expression Complexity' + category: security + license: Commons Clause License Condition v1.0[LGPL-2.1-only] + technology: + - python + references: + - 'https://docs.python.org/3/library/re.html' +- id: python.lang.security.audit.sqli.aiopg-sqli.aiopg-sqli + languages: + - python + message: >- + Detected string concatenation with a non-literal variable in an aiopg + Python SQL statement. This could lead to SQL injection if the variable is user-controlled + and not properly sanitized. In order to prevent SQL injection, + use parameterized queries instead. + You can create parameterized queries like so: + 'cur.execute("SELECT %s FROM table", (user_value,))'. + metadata: + references: + - https://github.com/aio-libs/aiopg + category: security + cwe: + - "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')" + technology: + - aiopg + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH + confidence: LOW + patterns: + - pattern-either: + - patterns: + - pattern: $CUR.$METHOD(...,$QUERY,...) + - pattern-either: + - pattern-inside: | + $QUERY = $X + $Y + ... + - pattern-inside: | + $QUERY += $X + ... + - pattern-inside: | + $QUERY = '...'.format(...) + ... + - pattern-inside: | + $QUERY = '...' % (...) + ... + - pattern-inside: | + $QUERY = f'...{$USERINPUT}...' + ... + - pattern-not-inside: | + $QUERY += "..." + ... + - pattern-not-inside: | + $QUERY = "..." + "..." + ... + - pattern-not-inside: | + $QUERY = '...'.format() + ... + - pattern-not-inside: | + $QUERY = '...' % () + ... + - pattern: $CUR.$METHOD(..., $X + $Y, ...) + - pattern: $CUR.$METHOD(..., '...'.format(...), ...) + - pattern: $CUR.$METHOD(..., '...' % (...), ...) + - pattern: $CUR.$METHOD(..., f'...{$USERINPUT}...', ...) + - pattern-either: + - pattern-inside: | + $CONN = await aiopg.connect(...) + ... + $CUR = await $CONN.cursor(...) + ... + - pattern-inside: | + $POOL = await aiopg.create_pool(...) + ... + async with $POOL.acquire(...) as $CONN: + ... + async with $CONN.cursor(...) as $CUR: + ... + - pattern-inside: | + $POOL = await aiopg.create_pool(...) + ... + with (await $POOL.cursor(...)) as $CUR: + ... + - pattern-inside: | + $POOL = await aiopg.create_pool(...) + ... + async with $POOL as $CONN: + ... + $CUR = await $CONN.cursor(...) + ... + - pattern-inside: | + $POOL = await aiopg.create_pool(...) + ... + async with $POOL.cursor(...) as $CUR: + ... + - pattern-not: $CUR.$METHOD(..., "..." + "...", ...) + - pattern-not: $CUR.$METHOD(..., '...'.format(), ...) + - pattern-not: $CUR.$METHOD(..., '...'%(), ...) + - metavariable-regex: + metavariable: $METHOD + regex: ^(execute)$ + severity: WARNING +- id: python.lang.security.audit.sqli.asyncpg-sqli.asyncpg-sqli + languages: + - python + message: >- + Detected string concatenation with a non-literal variable in a asyncpg + Python SQL statement. This could lead to SQL injection if the variable is user-controlled + and not properly sanitized. In order to prevent SQL injection, + use parameterized queries or prepared statements instead. + You can create parameterized queries like so: + 'conn.fetch("SELECT $1 FROM table", value)'. + You can also create prepared statements with 'Connection.prepare': + 'stmt = conn.prepare("SELECT $1 FROM table"); await stmt.fetch(user_value)' + metadata: + references: + - https://github.com/MagicStack/asyncpg + - https://magicstack.github.io/asyncpg/current/ + category: security + cwe: + - "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')" + technology: + - asyncpg + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH + confidence: LOW + patterns: + - pattern-either: + - patterns: + - pattern: $CONN.$METHOD(...,$QUERY,...) + - pattern-either: + - pattern-inside: | + $QUERY = $X + $Y + ... + - pattern-inside: | + $QUERY += $X + ... + - pattern-inside: | + $QUERY = '...'.format(...) + ... + - pattern-inside: | + $QUERY = '...' % (...) + ... + - pattern-inside: | + $QUERY = f'...{$USERINPUT}...' + ... + - pattern-not-inside: | + $QUERY += "..." + ... + - pattern-not-inside: | + $QUERY = "..." + "..." + ... + - pattern-not-inside: | + $QUERY = '...'.format() + ... + - pattern-not-inside: | + $QUERY = '...' % () + ... + - pattern: $CONN.$METHOD(..., $X + $Y, ...) + - pattern: $CONN.$METHOD(..., $Y.format(...), ...) + - pattern: $CONN.$METHOD(..., '...'.format(...), ...) + - pattern: $CONN.$METHOD(..., '...' % (...), ...) + - pattern: $CONN.$METHOD(..., f'...{$USERINPUT}...', ...) + - pattern-either: + - pattern-inside: | + $CONN = await asyncpg.connect(...) + ... + - pattern-inside: | + async with asyncpg.create_pool(...) as $CONN: + ... + - pattern-inside: | + async with $POOL.acquire(...) as $CONN: + ... + - pattern-inside: | + $CONN = await $POOL.acquire(...) + ... + - pattern-inside: | + def $FUNCNAME(..., $CONN: Connection, ...): + ... + - pattern-inside: | + def $FUNCNAME(..., $CONN: asyncpg.Connection, ...): + ... + - pattern-not: $CONN.$METHOD(..., "..." + "...", ...) + - pattern-not: $CONN.$METHOD(..., '...'.format(), ...) + - pattern-not: $CONN.$METHOD(..., '...'%(), ...) + - metavariable-regex: + metavariable: $METHOD + regex: ^(fetch|fetchrow|fetchval|execute|executemany|prepare|cursor|copyfromquery)$ + severity: WARNING +- id: python.lang.security.audit.sqli.pg8000-sqli.pg8000-sqli + languages: + - python + message: >- + Detected string concatenation with a non-literal variable in a pg8000 + Python SQL statement. This could lead to SQL injection if the variable is user-controlled + and not properly sanitized. In order to prevent SQL injection, + use parameterized queries or prepared statements instead. + You can create parameterized queries like so: + 'conn.run("SELECT :value FROM table", value=myvalue)'. + You can also create prepared statements with 'conn.prepare': + 'conn.prepare("SELECT (:v) FROM table")' + metadata: + references: + - https://github.com/tlocke/pg8000 + cwe: + - "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')" + category: security + technology: + - pg8000 + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH + confidence: LOW + patterns: + - pattern-either: + - patterns: + - pattern: $CONN.$METHOD(...,$QUERY,...) + - pattern-either: + - pattern-inside: | + $QUERY = $X + $Y + ... + - pattern-inside: | + $QUERY += $X + ... + - pattern-inside: | + $QUERY = '...'.format(...) + ... + - pattern-inside: | + $QUERY = '...' % (...) + ... + - pattern-inside: | + $QUERY = f'...{$USERINPUT}...' + ... + - pattern-not-inside: | + $QUERY += "..." + ... + - pattern-not-inside: | + $QUERY = "..." + "..." + ... + - pattern-not-inside: | + $QUERY = '...'.format() + ... + - pattern-not-inside: | + $QUERY = '...' % () + ... + - pattern: $CONN.$METHOD(..., $X + $Y, ...) + - pattern: $CONN.$METHOD(..., '...'.format(...), ...) + - pattern: $CONN.$METHOD(..., '...' % (...), ...) + - pattern: $CONN.$METHOD(..., f'...{$USERINPUT}...', ...) + - pattern-either: + - pattern-inside: | + $CONN = pg8000.native.Connection(...) + ... + - pattern-inside: | + $CONN = pg8000.dhapi.connect(...) + ... + - pattern-inside: | + $CONN1 = pg8000.connect(...) + ... + $CONN = $CONN1.cursor(...) + ... + - pattern-inside: | + $CONN = pg8000.connect(...) + ... + - pattern-not: $CONN.$METHOD(..., "..." + "...", ...) + - pattern-not: $CONN.$METHOD(..., '...'.format(), ...) + - pattern-not: $CONN.$METHOD(..., '...'%(), ...) + - metavariable-regex: + metavariable: $METHOD + regex: ^(run|execute|executemany|prepare)$ + severity: WARNING +- id: python.lang.security.audit.sqli.psycopg-sqli.psycopg-sqli + languages: + - python + message: >- + Detected string concatenation with a non-literal variable in a psycopg2 + Python SQL statement. This could lead to SQL injection if the variable is user-controlled + and not properly sanitized. In order to prevent SQL injection, + use parameterized queries or prepared statements instead. + You can use prepared statements by creating a 'sql.SQL' string. You can also use + the pyformat binding style to create + parameterized queries. For example: + 'cur.execute(SELECT * FROM table WHERE name=%s, user_input)' + metadata: + cwe: + - "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')" + references: + - https://www.psycopg.org/docs/sql.html + category: security + technology: + - psycopg + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH + confidence: LOW + patterns: + - pattern-either: + - patterns: + - pattern: $CUR.$METHOD(...,$QUERY,...) + - pattern-either: + - pattern-inside: | + $QUERY = $X + $Y + ... + - pattern-inside: | + $QUERY += $X + ... + - pattern-inside: | + $QUERY = '...'.format(...) + ... + - pattern-inside: | + $QUERY = '...' % (...) + ... + - pattern-inside: | + $QUERY = f'...{$USERINPUT}...' + ... + - pattern-not-inside: | + $QUERY += "..." + ... + - pattern-not-inside: | + $QUERY = "..." + "..." + ... + - pattern-not-inside: | + $QUERY = '...'.format() + ... + - pattern-not-inside: | + $QUERY = '...' % () + ... + - pattern: $CUR.$METHOD(..., $X + $Y, ...) + - pattern: $CUR.$METHOD(..., '...'.format(...), ...) + - pattern: $CUR.$METHOD(..., '...' % (...), ...) + - pattern: $CUR.$METHOD(..., f'...{$USERINPUT}...', ...) + - pattern-either: + - pattern-inside: | + $CONN = psycopg2.connect(...) + ... + $CUR = $CONN.cursor(...) + ... + - pattern-inside: | + $CONN = psycopg2.connect(...) + ... + with $CONN.cursor(...) as $CUR: + ... + - pattern-not: $CUR.$METHOD(..., "..." + "...", ...) + - pattern-not: $CUR.$METHOD(..., '...'.format(), ...) + - pattern-not: $CUR.$METHOD(..., '...'%(), ...) + - metavariable-regex: + metavariable: $METHOD + regex: ^(execute|executemany|mogrify)$ + severity: WARNING +- id: python.lang.security.audit.ssl-wrap-socket-is-deprecated.ssl-wrap-socket-is-deprecated + pattern: ssl.wrap_socket(...) + message: >- + 'ssl.wrap_socket()' is deprecated. This function creates an insecure socket + without server name indication or hostname matching. Instead, create an SSL + context using 'ssl.SSLContext()' and use that to wrap a socket. + metadata: + cwe: + - 'CWE-326: Inadequate Encryption Strength' + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + references: + - https://docs.python.org/3/library/ssl.html#ssl.wrap_socket + - https://docs.python.org/3/library/ssl.html#ssl.SSLContext.wrap_socket + category: security + technology: + - python + subcategory: + - vuln + likelihood: LOW + impact: MEDIUM + confidence: MEDIUM + languages: [python] + severity: WARNING +- id: python.lang.security.audit.subprocess-shell-true.subprocess-shell-true + patterns: + - pattern: subprocess.$FUNC(..., shell=True, ...) + - pattern-not: subprocess.$FUNC("...", shell=True, ...) + message: >- + Found 'subprocess' function '$FUNC' with 'shell=True'. This is dangerous because + this call will spawn + the command using a shell process. Doing so propagates current shell settings + and variables, which + makes it much easier for a malicious actor to execute commands. Use 'shell=False' + instead. + fix-regex: + regex: (shell\s*=\s*)True + replacement: \1False + metadata: + source-rule-url: https://bandit.readthedocs.io/en/latest/plugins/b602_subprocess_popen_with_shell_equals_true.html + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + cwe: + - "CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')" + references: + - https://stackoverflow.com/questions/3172470/actual-meaning-of-shell-true-in-subprocess + - https://docs.python.org/3/library/subprocess.html + category: security + technology: + - python + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: HIGH + impact: LOW + confidence: MEDIUM + languages: [python] + severity: ERROR +- id: python.lang.security.audit.system-wildcard-detected.system-wildcard-detected + patterns: + - pattern-either: + - pattern-inside: os.system("...") + - pattern-inside: os.popen("...") + - pattern-inside: os.popen2("...") + - pattern-inside: os.popen3("...") + - pattern-inside: os.popen4("...") + - pattern-inside: subprocess.$W(..., shell=True, ...) + - pattern-regex: (tar|chmod|chown|rsync)(.*?)\* + message: >- + Detected use of the wildcard character in a system call that spawns a shell. + This subjects the wildcard to normal shell expansion, which can have unintended + consequences + if there exist any non-standard file names. Consider a file named '-e sh script.sh' + -- this + will execute a script when 'rsync' is called. See + https://www.defensecode.com/public/DefenseCode_Unix_WildCards_Gone_Wild.txt + for more information. + metadata: + cwe: + - 'CWE-155: Improper Neutralization of Wildcards or Matching Symbols' + owasp: 'A01:2017 - Injection' + source-url-open: https://github.com/PyCQA/bandit/blob/b1411bfb43795d3ffd268bef17a839dee954c2b1/bandit/plugins/injection_wildcard.py + references: + - https://www.defensecode.com/public/DefenseCode_Unix_WildCards_Gone_Wild.txt + category: security + technology: + - python + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [python] + severity: WARNING +- id: python.lang.security.audit.telnetlib.telnetlib + pattern: telnetlib.$ANYTHING(...) + message: >- + Telnet does not encrypt communications. Use SSH instead. + metadata: + source-rule-url: https://github.com/PyCQA/bandit/blob/d5f8fa0d89d7b11442fc6ec80ca42953974354c8/bandit/blacklists/calls.py#L208 + cwe: + - 'CWE-319: Cleartext Transmission of Sensitive Information' + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + bandit-code: B312 + references: + - https://docs.python.org/3/library/telnetlib.html + category: security + technology: + - python + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + severity: WARNING + languages: + - python +- id: python.lang.security.audit.weak-ssl-version.weak-ssl-version + message: >- + An insecure SSL version was detected. TLS versions 1.0, 1.1, and all SSL versions + are considered weak encryption and are deprecated. + Use 'ssl.PROTOCOL_TLSv1_2' or higher. + metadata: + cwe: + - 'CWE-326: Inadequate Encryption Strength' + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + source-rule-url: https://github.com/PyCQA/bandit/blob/b1411bfb43795d3ffd268bef17a839dee954c2b1/bandit/plugins/insecure_ssl_tls.py#L30 + asvs: + section: V9 Communications Verification Requirements + control_id: 9.1.3 Weak TLS + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x17-V9-Communications.md#v91-client-communications-security-requirements + version: '4' + references: + - https://tools.ietf.org/html/rfc7568 + - https://tools.ietf.org/id/draft-ietf-tls-oldversions-deprecate-02.html + - https://docs.python.org/3/library/ssl.html#ssl.PROTOCOL_TLSv1_2 + category: security + technology: + - python + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: MEDIUM + languages: [python] + severity: WARNING + pattern-either: + - pattern: ssl.PROTOCOL_SSLv2 + - pattern: ssl.PROTOCOL_SSLv3 + - pattern: ssl.PROTOCOL_TLSv1 + - pattern: ssl.PROTOCOL_TLSv1_1 + - pattern: pyOpenSSL.SSL.SSLv2_METHOD + - pattern: pyOpenSSL.SSL.SSLv23_METHOD + - pattern: pyOpenSSL.SSL.SSLv3_METHOD + - pattern: pyOpenSSL.SSL.TLSv1_METHOD + - pattern: pyOpenSSL.SSL.TLSv1_1_METHOD +- id: python.lang.security.dangerous-code-run.dangerous-interactive-code-run + mode: taint + options: + symbolic_propagation: true + pattern-sources: + - patterns: + - pattern-either: + - patterns: + - pattern-either: + - pattern: flask.request.form.get(...) + - pattern: flask.request.form[...] + - pattern: flask.request.args.get(...) + - pattern: flask.request.args[...] + - pattern: flask.request.values.get(...) + - pattern: flask.request.values[...] + - pattern: flask.request.cookies.get(...) + - pattern: flask.request.cookies[...] + - pattern: flask.request.stream + - pattern: flask.request.headers.get(...) + - pattern: flask.request.headers[...] + - pattern: flask.request.data + - pattern: flask.request.full_path + - pattern: flask.request.url + - pattern: flask.request.json + - pattern: flask.request.get_json() + - pattern: flask.request.view_args.get(...) + - pattern: flask.request.view_args[...] + - patterns: + - pattern-inside: | + @$APP.route(...) + def $FUNC(..., $ROUTEVAR, ...): + ... + - focus-metavariable: $ROUTEVAR + - patterns: + - pattern-inside: | + def $FUNC(request, ...): + ... + - pattern-either: + - pattern: request.$PROPERTY.get(...) + - pattern: request.$PROPERTY[...] + - patterns: + - pattern-either: + - pattern-inside: | + @rest_framework.decorators.api_view(...) + def $FUNC($REQ, ...): + ... + - patterns: + - pattern-either: + - pattern-inside: | + class $VIEW(..., rest_framework.views.APIView, ...): + ... + - pattern-inside: | + class $VIEW(..., rest_framework.generics.GenericAPIView, ...): + ... + - pattern-inside: | + def $METHOD(self, $REQ, ...): + ... + - metavariable-regex: + metavariable: $METHOD + regex: (get|post|put|patch|delete|head) + - pattern-either: + - pattern: $REQ.POST.get(...) + - pattern: $REQ.POST[...] + - pattern: $REQ.FILES.get(...) + - pattern: $REQ.FILES[...] + - pattern: $REQ.DATA.get(...) + - pattern: $REQ.DATA[...] + - pattern: $REQ.QUERY_PARAMS.get(...) + - pattern: $REQ.QUERY_PARAMS[...] + - pattern: $REQ.data.get(...) + - pattern: $REQ.data[...] + - pattern: $REQ.query_params.get(...) + - pattern: $REQ.query_params[...] + - pattern: $REQ.content_type + - pattern: $REQ.content_type + - pattern: $REQ.stream + - pattern: $REQ.stream + - patterns: + - pattern-either: + - pattern-inside: | + class $SERVER(..., http.server.BaseHTTPRequestHandler, ...): + ... + - pattern-inside: | + class $SERVER(..., http.server.StreamRequestHandler, ...): + ... + - pattern-inside: | + class $SERVER(..., http.server.DatagramRequestHandler, ...): + ... + - pattern-either: + - pattern: self.requestline + - pattern: self.path + - pattern: self.headers[...] + - pattern: self.headers.get(...) + - pattern: self.rfile + - patterns: + - pattern-inside: | + @pyramid.view.view_config( ... ) + def $VIEW($REQ): + ... + - pattern: $REQ.$ANYTHING + - pattern-not: $REQ.dbsession + pattern-sinks: + - patterns: + - pattern-either: + - pattern-inside: | + $X = code.InteractiveConsole(...) + ... + - pattern-inside: | + $X = code.InteractiveInterpreter(...) + ... + - pattern-either: + - pattern: | + $X.push($PAYLOAD,...) + - pattern: | + $X.runsource($PAYLOAD,...) + - pattern: | + $X.runcode(code.compile_command($PAYLOAD),...) + - pattern: | + $PL = code.compile_command($PAYLOAD,...) + ... + $X.runcode($PL,...) + - focus-metavariable: $PAYLOAD + - pattern-not: | + $X.push("...",...) + - pattern-not: | + $X.runsource("...",...) + - pattern-not: | + $X.runcode(code.compile_command("..."),...) + - pattern-not: | + $PL = code.compile_command("...",...) + ... + $X.runcode($PL,...) + message: >- + Found user controlled data inside InteractiveConsole/InteractiveInterpreter method. + This is dangerous if external data can reach this function call because it allows + a malicious actor to run arbitrary Python code. + metadata: + cwe: + - "CWE-95: Improper Neutralization of Directives in Dynamically Evaluated Code ('Eval Injection')" + owasp: + - A03:2021 - Injection + references: + - https://semgrep.dev/docs/cheat-sheets/python-command-injection/ + category: security + technology: + - python + confidence: MEDIUM + subcategory: + - vuln + likelihood: MEDIUM + impact: HIGH + severity: WARNING + languages: + - python +- id: python.lang.security.dangerous-globals-use.dangerous-globals-use + patterns: + - pattern-either: + - pattern: globals().get(...) + - pattern: locals().get(...) + - pattern: globals()[...] + - pattern: locals()[...] + - patterns: + - pattern-either: + - pattern-inside: | + $G = globals() + ... + - pattern-inside: | + $G = locals() + ... + - pattern-either: + - pattern: $G.get(...) + - pattern: $G[...] + - pattern: $FUNC.__globals__[...] + - pattern-not: globals().get("...") + - pattern-not: locals().get("...") + - pattern-not: globals()["..."] + - pattern-not: locals()["..."] + - pattern-not: $G.get("...") + - pattern-not: $G.get["..."] + - pattern-not: $G["..."] + - pattern-not: $FUNC.__globals__["..."] + - pattern-not-inside: globals()[...] = ... + - pattern-not-inside: locals()[...] = ... + - pattern-not-inside: $G[...] = ... + - pattern-not-inside: $FUNC.__globals__[...] = ... + message: >- + Found non static data as an index to 'globals()'. This is extremely + dangerous because it allows an attacker to execute arbitrary code + on the system. Refactor your code not to use 'globals()'. + metadata: + cwe: + - "CWE-96: Improper Neutralization of Directives in Statically Saved Code ('Static Code Injection')" + owasp: + - A03:2021 - Injection + references: + - https://github.com/mpirnat/lets-be-bad-guys/blob/d92768fb3ade32956abd53bd6bb06e19d634a084/badguys/vulnerable/views.py#L181-L186 + category: security + technology: + - python + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + severity: WARNING + languages: [python] +- id: python.lang.security.dangerous-os-exec.dangerous-os-exec + mode: taint + options: + symbolic_propagation: true + pattern-sources: + - patterns: + - pattern-either: + - patterns: + - pattern-either: + - pattern: flask.request.form.get(...) + - pattern: flask.request.form[...] + - pattern: flask.request.args.get(...) + - pattern: flask.request.args[...] + - pattern: flask.request.values.get(...) + - pattern: flask.request.values[...] + - pattern: flask.request.cookies.get(...) + - pattern: flask.request.cookies[...] + - pattern: flask.request.stream + - pattern: flask.request.headers.get(...) + - pattern: flask.request.headers[...] + - pattern: flask.request.data + - pattern: flask.request.full_path + - pattern: flask.request.url + - pattern: flask.request.json + - pattern: flask.request.get_json() + - pattern: flask.request.view_args.get(...) + - pattern: flask.request.view_args[...] + - patterns: + - pattern-inside: | + @$APP.route(...) + def $FUNC(..., $ROUTEVAR, ...): + ... + - focus-metavariable: $ROUTEVAR + - patterns: + - pattern-inside: | + def $FUNC(request, ...): + ... + - pattern-either: + - pattern: request.$PROPERTY.get(...) + - pattern: request.$PROPERTY[...] + - patterns: + - pattern-either: + - pattern-inside: | + @rest_framework.decorators.api_view(...) + def $FUNC($REQ, ...): + ... + - patterns: + - pattern-either: + - pattern-inside: | + class $VIEW(..., rest_framework.views.APIView, ...): + ... + - pattern-inside: | + class $VIEW(..., rest_framework.generics.GenericAPIView, ...): + ... + - pattern-inside: | + def $METHOD(self, $REQ, ...): + ... + - metavariable-regex: + metavariable: $METHOD + regex: (get|post|put|patch|delete|head) + - pattern-either: + - pattern: $REQ.POST.get(...) + - pattern: $REQ.POST[...] + - pattern: $REQ.FILES.get(...) + - pattern: $REQ.FILES[...] + - pattern: $REQ.DATA.get(...) + - pattern: $REQ.DATA[...] + - pattern: $REQ.QUERY_PARAMS.get(...) + - pattern: $REQ.QUERY_PARAMS[...] + - pattern: $REQ.data.get(...) + - pattern: $REQ.data[...] + - pattern: $REQ.query_params.get(...) + - pattern: $REQ.query_params[...] + - pattern: $REQ.content_type + - pattern: $REQ.content_type + - pattern: $REQ.stream + - pattern: $REQ.stream + - patterns: + - pattern-either: + - pattern-inside: | + class $SERVER(..., http.server.BaseHTTPRequestHandler, ...): + ... + - pattern-inside: | + class $SERVER(..., http.server.StreamRequestHandler, ...): + ... + - pattern-inside: | + class $SERVER(..., http.server.DatagramRequestHandler, ...): + ... + - pattern-either: + - pattern: self.requestline + - pattern: self.path + - pattern: self.headers[...] + - pattern: self.headers.get(...) + - pattern: self.rfile + - patterns: + - pattern-inside: | + @pyramid.view.view_config( ... ) + def $VIEW($REQ): + ... + - pattern: $REQ.$ANYTHING + - pattern-not: $REQ.dbsession + pattern-sinks: + - patterns: + - pattern-either: + - patterns: + - pattern-not: os.$METHOD("...", ...) + - pattern: os.$METHOD(...) + - metavariable-regex: + metavariable: $METHOD + regex: (execl|execle|execlp|execlpe|execv|execve|execvp|execvpe) + - patterns: + - pattern-not: os.$METHOD("...", [$PATH,"...","...",...],...) + - pattern-inside: os.$METHOD($BASH,[$PATH,"-c",$CMD,...],...) + - pattern: $CMD + - metavariable-regex: + metavariable: $METHOD + regex: (execv|execve|execvp|execvpe) + - metavariable-regex: + metavariable: $BASH + regex: (.*)(sh|bash|ksh|csh|tcsh|zsh) + - patterns: + - pattern-not: os.$METHOD("...", $PATH, "...", "...",...) + - pattern-inside: os.$METHOD($BASH, $PATH, "-c", $CMD,...) + - pattern: $CMD + - metavariable-regex: + metavariable: $METHOD + regex: (execl|execle|execlp|execlpe) + - metavariable-regex: + metavariable: $BASH + regex: (.*)(sh|bash|ksh|csh|tcsh|zsh) + message: >- + Found user controlled content when spawning a process. This is dangerous because it allows + a malicious actor to execute commands. + metadata: + cwe: + - "CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')" + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + references: + - https://semgrep.dev/docs/cheat-sheets/python-command-injection/ + asvs: + section: 'V5: Validation, Sanitization and Encoding Verification Requirements' + control_id: 5.3.8 OS Command Injection + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x13-V5-Validation-Sanitization-Encoding.md#v53-output-encoding-and-injection-prevention-requirements + version: '4' + confidence: MEDIUM + category: security + technology: + - python + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + languages: [python] + severity: ERROR +- id: python.lang.security.dangerous-spawn-process.dangerous-spawn-process + mode: taint + options: + symbolic_propagation: true + pattern-sources: + - patterns: + - pattern-either: + - patterns: + - pattern-either: + - pattern: flask.request.form.get(...) + - pattern: flask.request.form[...] + - pattern: flask.request.args.get(...) + - pattern: flask.request.args[...] + - pattern: flask.request.values.get(...) + - pattern: flask.request.values[...] + - pattern: flask.request.cookies.get(...) + - pattern: flask.request.cookies[...] + - pattern: flask.request.stream + - pattern: flask.request.headers.get(...) + - pattern: flask.request.headers[...] + - pattern: flask.request.data + - pattern: flask.request.full_path + - pattern: flask.request.url + - pattern: flask.request.json + - pattern: flask.request.get_json() + - pattern: flask.request.view_args.get(...) + - pattern: flask.request.view_args[...] + - patterns: + - pattern-inside: | + @$APP.route(...) + def $FUNC(..., $ROUTEVAR, ...): + ... + - pattern: $ROUTEVAR + - patterns: + - pattern-inside: | + def $FUNC(request, ...): + ... + - pattern-either: + - pattern: request.$PROPERTY.get(...) + - pattern: request.$PROPERTY[...] + - patterns: + - pattern-either: + - pattern-inside: | + @rest_framework.decorators.api_view(...) + def $FUNC($REQ, ...): + ... + - patterns: + - pattern-either: + - pattern-inside: | + class $VIEW(..., rest_framework.views.APIView, ...): + ... + - pattern-inside: | + class $VIEW(..., rest_framework.generics.GenericAPIView, ...): + ... + - pattern-inside: | + def $METHOD(self, $REQ, ...): + ... + - metavariable-regex: + metavariable: $METHOD + regex: (get|post|put|patch|delete|head) + - pattern-either: + - pattern: $REQ.POST.get(...) + - pattern: $REQ.POST[...] + - pattern: $REQ.FILES.get(...) + - pattern: $REQ.FILES[...] + - pattern: $REQ.DATA.get(...) + - pattern: $REQ.DATA[...] + - pattern: $REQ.QUERY_PARAMS.get(...) + - pattern: $REQ.QUERY_PARAMS[...] + - pattern: $REQ.data.get(...) + - pattern: $REQ.data[...] + - pattern: $REQ.query_params.get(...) + - pattern: $REQ.query_params[...] + - pattern: $REQ.content_type + - pattern: $REQ.content_type + - pattern: $REQ.stream + - pattern: $REQ.stream + - patterns: + - pattern-either: + - pattern-inside: | + class $SERVER(..., http.server.BaseHTTPRequestHandler, ...): + ... + - pattern-inside: | + class $SERVER(..., http.server.StreamRequestHandler, ...): + ... + - pattern-inside: | + class $SERVER(..., http.server.DatagramRequestHandler, ...): + ... + - pattern-either: + - pattern: self.requestline + - pattern: self.path + - pattern: self.headers[...] + - pattern: self.headers.get(...) + - pattern: self.rfile + - patterns: + - pattern-inside: | + @pyramid.view.view_config( ... ) + def $VIEW($REQ): + ... + - pattern: $REQ.$ANYTHING + - pattern-not: $REQ.dbsession + - patterns: + - pattern-either: + - pattern: os.environ['$ANYTHING'] + - pattern: os.environ.get('$FOO', ...) + - pattern: os.environb['$ANYTHING'] + - pattern: os.environb.get('$FOO', ...) + - pattern: os.getenv('$ANYTHING', ...) + - pattern: os.getenvb('$ANYTHING', ...) + - patterns: + - pattern-either: + - patterns: + - pattern-either: + - pattern: sys.argv[...] + - pattern: sys.orig_argv[...] + - patterns: + - pattern-inside: | + $PARSER = argparse.ArgumentParser(...) + ... + - pattern-inside: | + $ARGS = $PARSER.parse_args() + - pattern: <... $ARGS ...> + - patterns: + - pattern-inside: | + $PARSER = optparse.OptionParser(...) + ... + - pattern-inside: | + $ARGS = $PARSER.parse_args() + - pattern: <... $ARGS ...> + - patterns: + - pattern-either: + - pattern-inside: | + $OPTS, $ARGS = getopt.getopt(...) + ... + - pattern-inside: | + $OPTS, $ARGS = getopt.gnu_getopt(...) + ... + - pattern-either: + - patterns: + - pattern-inside: | + for $O, $A in $OPTS: + ... + - pattern: $A + - pattern: $ARGS + pattern-sinks: + - patterns: + - pattern-either: + - patterns: + - pattern-not: os.$METHOD($MODE, "...", ...) + - pattern-inside: os.$METHOD($MODE, $CMD, ...) + - pattern: $CMD + - metavariable-regex: + metavariable: $METHOD + regex: (spawnl|spawnle|spawnlp|spawnlpe|spawnv|spawnve|spawnvp|spawnvp|spawnvpe|posix_spawn|posix_spawnp|startfile) + - patterns: + - pattern-not: os.$METHOD($MODE, "...", ["...","...",...], ...) + - pattern-inside: os.$METHOD($MODE, $BASH, ["-c",$CMD,...],...) + - pattern: $CMD + - metavariable-regex: + metavariable: $METHOD + regex: (spawnv|spawnve|spawnvp|spawnvp|spawnvpe|posix_spawn|posix_spawnp) + - metavariable-regex: + metavariable: $BASH + regex: (.*)(sh|bash|ksh|csh|tcsh|zsh) + - patterns: + - pattern-not: os.$METHOD($MODE, "...", "...", "...", ...) + - pattern-inside: os.$METHOD($MODE, $BASH, "-c", $CMD,...) + - pattern: $CMD + - metavariable-regex: + metavariable: $METHOD + regex: (spawnl|spawnle|spawnlp|spawnlpe) + - metavariable-regex: + metavariable: $BASH + regex: (.*)(sh|bash|ksh|csh|tcsh|zsh) + message: >- + Found user controlled content when spawning a process. This is dangerous because it allows a malicious + actor to + execute commands. + metadata: + source-rule-url: https://bandit.readthedocs.io/en/latest/plugins/b605_start_process_with_a_shell.html + cwe: + - "CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')" + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + references: + - https://semgrep.dev/docs/cheat-sheets/python-command-injection/ + asvs: + section: 'V5: Validation, Sanitization and Encoding Verification Requirements' + control_id: 5.3.8 OS Command Injection + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x13-V5-Validation-Sanitization-Encoding.md#v53-output-encoding-and-injection-prevention-requirements + version: '4' + category: security + technology: + - python + confidence: MEDIUM + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + languages: [python] + severity: ERROR +- id: python.lang.security.dangerous-subinterpreters-run-string.dangerous-subinterpreters-run-string + mode: taint + options: + symbolic_propagation: true + pattern-sources: + - patterns: + - pattern-either: + - patterns: + - pattern-either: + - pattern: flask.request.form.get(...) + - pattern: flask.request.form[...] + - pattern: flask.request.args.get(...) + - pattern: flask.request.args[...] + - pattern: flask.request.values.get(...) + - pattern: flask.request.values[...] + - pattern: flask.request.cookies.get(...) + - pattern: flask.request.cookies[...] + - pattern: flask.request.stream + - pattern: flask.request.headers.get(...) + - pattern: flask.request.headers[...] + - pattern: flask.request.data + - pattern: flask.request.full_path + - pattern: flask.request.url + - pattern: flask.request.json + - pattern: flask.request.get_json() + - pattern: flask.request.view_args.get(...) + - pattern: flask.request.view_args[...] + - patterns: + - pattern-inside: | + @$APP.route(...) + def $FUNC(..., $ROUTEVAR, ...): + ... + - focus-metavariable: $ROUTEVAR + - patterns: + - pattern-inside: | + def $FUNC(request, ...): + ... + - pattern-either: + - pattern: request.$PROPERTY.get(...) + - pattern: request.$PROPERTY[...] + - patterns: + - pattern-either: + - pattern-inside: | + @rest_framework.decorators.api_view(...) + def $FUNC($REQ, ...): + ... + - patterns: + - pattern-either: + - pattern-inside: | + class $VIEW(..., rest_framework.views.APIView, ...): + ... + - pattern-inside: | + class $VIEW(..., rest_framework.generics.GenericAPIView, ...): + ... + - pattern-inside: | + def $METHOD(self, $REQ, ...): + ... + - metavariable-regex: + metavariable: $METHOD + regex: (get|post|put|patch|delete|head) + - pattern-either: + - pattern: $REQ.POST.get(...) + - pattern: $REQ.POST[...] + - pattern: $REQ.FILES.get(...) + - pattern: $REQ.FILES[...] + - pattern: $REQ.DATA.get(...) + - pattern: $REQ.DATA[...] + - pattern: $REQ.QUERY_PARAMS.get(...) + - pattern: $REQ.QUERY_PARAMS[...] + - pattern: $REQ.data.get(...) + - pattern: $REQ.data[...] + - pattern: $REQ.query_params.get(...) + - pattern: $REQ.query_params[...] + - pattern: $REQ.content_type + - pattern: $REQ.content_type + - pattern: $REQ.stream + - pattern: $REQ.stream + - patterns: + - pattern-either: + - pattern-inside: | + class $SERVER(..., http.server.BaseHTTPRequestHandler, ...): + ... + - pattern-inside: | + class $SERVER(..., http.server.StreamRequestHandler, ...): + ... + - pattern-inside: | + class $SERVER(..., http.server.DatagramRequestHandler, ...): + ... + - pattern-either: + - pattern: self.requestline + - pattern: self.path + - pattern: self.headers[...] + - pattern: self.headers.get(...) + - pattern: self.rfile + - patterns: + - pattern-inside: | + @pyramid.view.view_config( ... ) + def $VIEW($REQ): + ... + - pattern: $REQ.$ANYTHING + - pattern-not: $REQ.dbsession + pattern-sinks: + - patterns: + - pattern: | + _xxsubinterpreters.run_string($ID, $PAYLOAD, ...) + - pattern-not: | + _xxsubinterpreters.run_string($ID, "...", ...) + - focus-metavariable: $PAYLOAD + message: >- + Found user controlled content in `run_string`. + This is dangerous because it allows a malicious actor to run arbitrary Python code. + metadata: + cwe: + - "CWE-95: Improper Neutralization of Directives in Dynamically Evaluated Code ('Eval Injection')" + owasp: + - A03:2021 - Injection + references: + - https://bugs.python.org/issue43472 + - https://semgrep.dev/docs/cheat-sheets/python-command-injection/ + category: security + technology: + - python + confidence: MEDIUM + subcategory: + - vuln + likelihood: MEDIUM + impact: HIGH + severity: WARNING + languages: + - python +- id: python.lang.security.dangerous-subprocess-use.dangerous-subprocess-use + mode: taint + options: + symbolic_propagation: true + pattern-sources: + - patterns: + - pattern-either: + - patterns: + - pattern-either: + - pattern: flask.request.form.get(...) + - pattern: flask.request.form[...] + - pattern: flask.request.args.get(...) + - pattern: flask.request.args[...] + - pattern: flask.request.values.get(...) + - pattern: flask.request.values[...] + - pattern: flask.request.cookies.get(...) + - pattern: flask.request.cookies[...] + - pattern: flask.request.stream + - pattern: flask.request.headers.get(...) + - pattern: flask.request.headers[...] + - pattern: flask.request.data + - pattern: flask.request.full_path + - pattern: flask.request.url + - pattern: flask.request.json + - pattern: flask.request.get_json() + - pattern: flask.request.view_args.get(...) + - pattern: flask.request.view_args[...] + - patterns: + - pattern-inside: | + @$APP.route(...) + def $FUNC(..., $ROUTEVAR, ...): + ... + - focus-metavariable: $ROUTEVAR + - patterns: + - pattern-inside: | + def $FUNC(request, ...): + ... + - pattern-either: + - pattern: request.$PROPERTY.get(...) + - pattern: request.$PROPERTY[...] + - patterns: + - pattern-either: + - pattern-inside: | + @rest_framework.decorators.api_view(...) + def $FUNC($REQ, ...): + ... + - patterns: + - pattern-either: + - pattern-inside: | + class $VIEW(..., rest_framework.views.APIView, ...): + ... + - pattern-inside: | + class $VIEW(..., rest_framework.generics.GenericAPIView, ...): + ... + - pattern-inside: | + def $METHOD(self, $REQ, ...): + ... + - metavariable-regex: + metavariable: $METHOD + regex: (get|post|put|patch|delete|head) + - pattern-either: + - pattern: $REQ.POST.get(...) + - pattern: $REQ.POST[...] + - pattern: $REQ.FILES.get(...) + - pattern: $REQ.FILES[...] + - pattern: $REQ.DATA.get(...) + - pattern: $REQ.DATA[...] + - pattern: $REQ.QUERY_PARAMS.get(...) + - pattern: $REQ.QUERY_PARAMS[...] + - pattern: $REQ.data.get(...) + - pattern: $REQ.data[...] + - pattern: $REQ.query_params.get(...) + - pattern: $REQ.query_params[...] + - pattern: $REQ.content_type + - pattern: $REQ.content_type + - pattern: $REQ.stream + - pattern: $REQ.stream + - patterns: + - pattern-either: + - pattern-inside: | + class $SERVER(..., http.server.BaseHTTPRequestHandler, ...): + ... + - pattern-inside: | + class $SERVER(..., http.server.StreamRequestHandler, ...): + ... + - pattern-inside: | + class $SERVER(..., http.server.DatagramRequestHandler, ...): + ... + - pattern-either: + - pattern: self.requestline + - pattern: self.path + - pattern: self.headers[...] + - pattern: self.headers.get(...) + - pattern: self.rfile + - patterns: + - pattern-inside: | + @pyramid.view.view_config( ... ) + def $VIEW($REQ): + ... + - pattern: $REQ.$ANYTHING + - pattern-not: $REQ.dbsession + pattern-sinks: + - patterns: + - pattern-either: + - patterns: + - pattern-not: subprocess.$FUNC("...", ...) + - pattern-not: subprocess.$FUNC(["...",...], ...) + - pattern-not: subprocess.$FUNC(("...",...), ...) + - pattern-not: subprocess.CalledProcessError(...) + - pattern-not: subprocess.SubprocessError(...) + - pattern: subprocess.$FUNC($CMD, ...) + - patterns: + - pattern-not: subprocess.$FUNC("=~/(sh|bash|ksh|csh|tcsh|zsh)/","-c","...",...) + - pattern: subprocess.$FUNC("=~/(sh|bash|ksh|csh|tcsh|zsh)/","-c", $CMD) + - patterns: + - pattern-not: subprocess.$FUNC(["=~/(sh|bash|ksh|csh|tcsh|zsh)/","-c","...",...],...) + - pattern-not: subprocess.$FUNC(("=~/(sh|bash|ksh|csh|tcsh|zsh)/","-c","...",...),...) + - pattern-either: + - pattern: subprocess.$FUNC(["=~/(sh|bash|ksh|csh|tcsh|zsh)/","-c", $CMD], ...) + - pattern: subprocess.$FUNC(("=~/(sh|bash|ksh|csh|tcsh|zsh)/","-c", $CMD), ...) + - patterns: + - pattern-not: subprocess.$FUNC("=~/(python)/","...",...) + - pattern: subprocess.$FUNC("=~/(python)/", $CMD) + - patterns: + - pattern-not: subprocess.$FUNC(["=~/(python)/","...",...],...) + - pattern-not: subprocess.$FUNC(("=~/(python)/","...",...),...) + - pattern-either: + - pattern: subprocess.$FUNC(["=~/(python)/", $CMD],...) + - pattern: subprocess.$FUNC(("=~/(python)/", $CMD),...) + - focus-metavariable: $CMD + message: >- + Detected subprocess function '$FUNC' with user controlled data. A malicious actor + could leverage this to perform command injection. + You may consider using 'shlex.escape()'. + metadata: + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + cwe: + - "CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')" + asvs: + section: 'V5: Validation, Sanitization and Encoding Verification Requirements' + control_id: 5.3.8 OS Command Injection + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x13-V5-Validation-Sanitization-Encoding.md#v53-output-encoding-and-injection-prevention-requirements + version: '4' + references: + - https://stackoverflow.com/questions/3172470/actual-meaning-of-shell-true-in-subprocess + - https://docs.python.org/3/library/subprocess.html + - https://docs.python.org/3/library/shlex.html + - https://semgrep.dev/docs/cheat-sheets/python-command-injection/ + category: security + technology: + - python + confidence: MEDIUM + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: HIGH + languages: [python] + severity: ERROR +- id: python.lang.security.dangerous-system-call.dangerous-system-call + mode: taint + options: + symbolic_propagation: true + pattern-sources: + - patterns: + - pattern-either: + - patterns: + - pattern-either: + - pattern: flask.request.form.get(...) + - pattern: flask.request.form[...] + - pattern: flask.request.args.get(...) + - pattern: flask.request.args[...] + - pattern: flask.request.values.get(...) + - pattern: flask.request.values[...] + - pattern: flask.request.cookies.get(...) + - pattern: flask.request.cookies[...] + - pattern: flask.request.stream + - pattern: flask.request.headers.get(...) + - pattern: flask.request.headers[...] + - pattern: flask.request.data + - pattern: flask.request.full_path + - pattern: flask.request.url + - pattern: flask.request.json + - pattern: flask.request.get_json() + - pattern: flask.request.view_args.get(...) + - pattern: flask.request.view_args[...] + - patterns: + - pattern-inside: | + @$APP.route(...) + def $FUNC(..., $ROUTEVAR, ...): + ... + - focus-metavariable: $ROUTEVAR + - patterns: + - pattern-inside: | + def $FUNC(request, ...): + ... + - pattern-either: + - pattern: request.$PROPERTY.get(...) + - pattern: request.$PROPERTY[...] + - patterns: + - pattern-either: + - pattern-inside: | + @rest_framework.decorators.api_view(...) + def $FUNC($REQ, ...): + ... + - patterns: + - pattern-either: + - pattern-inside: | + class $VIEW(..., rest_framework.views.APIView, ...): + ... + - pattern-inside: | + class $VIEW(..., rest_framework.generics.GenericAPIView, ...): + ... + - pattern-inside: | + def $METHOD(self, $REQ, ...): + ... + - metavariable-regex: + metavariable: $METHOD + regex: (get|post|put|patch|delete|head) + - pattern-either: + - pattern: $REQ.POST.get(...) + - pattern: $REQ.POST[...] + - pattern: $REQ.FILES.get(...) + - pattern: $REQ.FILES[...] + - pattern: $REQ.DATA.get(...) + - pattern: $REQ.DATA[...] + - pattern: $REQ.QUERY_PARAMS.get(...) + - pattern: $REQ.QUERY_PARAMS[...] + - pattern: $REQ.data.get(...) + - pattern: $REQ.data[...] + - pattern: $REQ.query_params.get(...) + - pattern: $REQ.query_params[...] + - pattern: $REQ.content_type + - pattern: $REQ.content_type + - pattern: $REQ.stream + - pattern: $REQ.stream + - patterns: + - pattern-either: + - pattern-inside: | + class $SERVER(..., http.server.BaseHTTPRequestHandler, ...): + ... + - pattern-inside: | + class $SERVER(..., http.server.StreamRequestHandler, ...): + ... + - pattern-inside: | + class $SERVER(..., http.server.DatagramRequestHandler, ...): + ... + - pattern-either: + - pattern: self.requestline + - pattern: self.path + - pattern: self.headers[...] + - pattern: self.headers.get(...) + - pattern: self.rfile + - patterns: + - pattern-inside: | + @pyramid.view.view_config( ... ) + def $VIEW($REQ): + ... + - pattern: $REQ.$ANYTHING + - pattern-not: $REQ.dbsession + pattern-sinks: + - patterns: + - pattern-not: os.$W("...", ...) + - pattern-either: + - pattern: os.system(...) + - pattern: getattr(os, "system")(...) + - pattern: __import__("os").system(...) + - pattern: getattr(__import__("os"), "system")(...) + - pattern: | + $X = __import__("os") + ... + $X.system(...) + - pattern: | + $X = __import__("os") + ... + getattr($X, "system")(...) + - pattern: | + $X = getattr(os, "system") + ... + $X(...) + - pattern: | + $X = __import__("os") + ... + $Y = getattr($X, "system") + ... + $Y(...) + - pattern: os.popen(...) + - pattern: os.popen2(...) + - pattern: os.popen3(...) + - pattern: os.popen4(...) + message: >- + Found user-controlled data used in a system call. This could allow a + malicious actor to execute commands. Use the 'subprocess' module instead, + which is easier to use without accidentally exposing a command injection + vulnerability. + metadata: + source-rule-url: https://bandit.readthedocs.io/en/latest/plugins/b605_start_process_with_a_shell.html + cwe: + - "CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')" + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + references: + - https://semgrep.dev/docs/cheat-sheets/python-command-injection/ + asvs: + section: 'V5: Validation, Sanitization and Encoding Verification Requirements' + control_id: 5.2.4 Dyanmic Code Execution Features + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x13-V5-Validation-Sanitization-Encoding.md#v52-sanitization-and-sandboxing-requirements + version: '4' + category: security + technology: + - python + confidence: MEDIUM + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: HIGH + impact: HIGH + languages: [python] + severity: ERROR +- id: python.lang.security.dangerous-testcapi-run-in-subinterp.dangerous-testcapi-run-in-subinterp + mode: taint + options: + symbolic_propagation: true + pattern-sources: + - patterns: + - pattern-either: + - patterns: + - pattern-either: + - pattern: flask.request.form.get(...) + - pattern: flask.request.form[...] + - pattern: flask.request.args.get(...) + - pattern: flask.request.args[...] + - pattern: flask.request.values.get(...) + - pattern: flask.request.values[...] + - pattern: flask.request.cookies.get(...) + - pattern: flask.request.cookies[...] + - pattern: flask.request.stream + - pattern: flask.request.headers.get(...) + - pattern: flask.request.headers[...] + - pattern: flask.request.data + - pattern: flask.request.full_path + - pattern: flask.request.url + - pattern: flask.request.json + - pattern: flask.request.get_json() + - pattern: flask.request.view_args.get(...) + - pattern: flask.request.view_args[...] + - patterns: + - pattern-inside: | + @$APP.route(...) + def $FUNC(..., $ROUTEVAR, ...): + ... + - focus-metavariable: $ROUTEVAR + - patterns: + - pattern-inside: | + def $FUNC(request, ...): + ... + - pattern-either: + - pattern: request.$PROPERTY.get(...) + - pattern: request.$PROPERTY[...] + - patterns: + - pattern-either: + - pattern-inside: | + @rest_framework.decorators.api_view(...) + def $FUNC($REQ, ...): + ... + - patterns: + - pattern-either: + - pattern-inside: | + class $VIEW(..., rest_framework.views.APIView, ...): + ... + - pattern-inside: | + class $VIEW(..., rest_framework.generics.GenericAPIView, ...): + ... + - pattern-inside: | + def $METHOD(self, $REQ, ...): + ... + - metavariable-regex: + metavariable: $METHOD + regex: (get|post|put|patch|delete|head) + - pattern-either: + - pattern: $REQ.POST.get(...) + - pattern: $REQ.POST[...] + - pattern: $REQ.FILES.get(...) + - pattern: $REQ.FILES[...] + - pattern: $REQ.DATA.get(...) + - pattern: $REQ.DATA[...] + - pattern: $REQ.QUERY_PARAMS.get(...) + - pattern: $REQ.QUERY_PARAMS[...] + - pattern: $REQ.data.get(...) + - pattern: $REQ.data[...] + - pattern: $REQ.query_params.get(...) + - pattern: $REQ.query_params[...] + - pattern: $REQ.content_type + - pattern: $REQ.content_type + - pattern: $REQ.stream + - pattern: $REQ.stream + - patterns: + - pattern-either: + - pattern-inside: | + class $SERVER(..., http.server.BaseHTTPRequestHandler, ...): + ... + - pattern-inside: | + class $SERVER(..., http.server.StreamRequestHandler, ...): + ... + - pattern-inside: | + class $SERVER(..., http.server.DatagramRequestHandler, ...): + ... + - pattern-either: + - pattern: self.requestline + - pattern: self.path + - pattern: self.headers[...] + - pattern: self.headers.get(...) + - pattern: self.rfile + - patterns: + - pattern-inside: | + @pyramid.view.view_config( ... ) + def $VIEW($REQ): + ... + - pattern: $REQ.$ANYTHING + - pattern-not: $REQ.dbsession + pattern-sinks: + - patterns: + - pattern-either: + - pattern: | + _testcapi.run_in_subinterp($PAYLOAD, ...) + - pattern: | + test.support.run_in_subinterp($PAYLOAD, ...) + - focus-metavariable: $PAYLOAD + - pattern-not: | + _testcapi.run_in_subinterp("...", ...) + - pattern-not: | + test.support.run_in_subinterp("...", ...) + message: >- + Found user controlled content in `run_in_subinterp`. + This is dangerous because it allows a malicious actor to run arbitrary Python code. + metadata: + cwe: + - "CWE-95: Improper Neutralization of Directives in Dynamically Evaluated Code ('Eval Injection')" + owasp: + - A03:2021 - Injection + references: + - https://semgrep.dev/docs/cheat-sheets/python-command-injection/ + category: security + technology: + - python + confidence: MEDIUM + subcategory: + - vuln + likelihood: HIGH + impact: HIGH + severity: WARNING + languages: + - python +- id: python.lang.security.deserialization.avoid-jsonpickle.avoid-jsonpickle + patterns: + - pattern: | + jsonpickle.decode($PAYLOAD,...) + - pattern-not: | + jsonpickle.decode("...",...) + metadata: + owasp: + - A08:2017 - Insecure Deserialization + - A08:2021 - Software and Data Integrity Failures + cwe: + - 'CWE-502: Deserialization of Untrusted Data' + references: + - https://github.com/jsonpickle/jsonpickle#jsonpickle + - https://www.exploit-db.com/exploits/49585 + category: security + technology: + - jsonpickle + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + message: >- + Avoid using `jsonpickle`, which is known to lead to code execution vulnerabilities. + When unpickling, the serialized data could be manipulated to run arbitrary code. + Instead, consider serializing the relevant data using `json` module. + languages: [python] + severity: WARNING +- id: python.lang.security.deserialization.avoid-pyyaml-load.avoid-pyyaml-load + metadata: + owasp: + - A08:2017 - Insecure Deserialization + - A08:2021 - Software and Data Integrity Failures + cwe: + - 'CWE-502: Deserialization of Untrusted Data' + references: + - https://github.com/yaml/pyyaml/wiki/PyYAML-yaml.load(input)-Deprecation + - https://nvd.nist.gov/vuln/detail/CVE-2017-18342 + category: security + technology: + - pyyaml + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: MEDIUM + languages: + - python + message: >- + Detected a possible YAML deserialization vulnerability. `yaml.unsafe_load`, `yaml.Loader`, + `yaml.CLoader`, and `yaml.UnsafeLoader` are all known to be unsafe methods of deserializing YAML. + An attacker with control over the YAML input could create special YAML input that allows the attacker + to run arbitrary Python code. This would allow the attacker to steal files, download and install malware, + or otherwise take over the machine. Use `yaml.safe_load` or `yaml.SafeLoader` instead. + fix-regex: + regex: unsafe_load + replacement: safe_load + count: 1 + severity: ERROR + patterns: + - pattern-inside: | + import yaml + ... + - pattern-not-inside: | + $YAML = ruamel.yaml.YAML(...) + ... + - pattern-either: + - pattern: yaml.unsafe_load(...) + - pattern: yaml.load(..., Loader=yaml.Loader, ...) + - pattern: yaml.load(..., Loader=yaml.UnsafeLoader, ...) + - pattern: yaml.load(..., Loader=yaml.CLoader, ...) + - pattern: yaml.load_all(..., Loader=yaml.Loader, ...) + - pattern: yaml.load_all(..., Loader=yaml.UnsafeLoader, ...) + - pattern: yaml.load_all(..., Loader=yaml.CLoader, ...) +- id: python.lang.security.deserialization.avoid-unsafe-ruamel.avoid-unsafe-ruamel + metadata: + owasp: + - A08:2017 - Insecure Deserialization + - A08:2021 - Software and Data Integrity Failures + cwe: + - 'CWE-502: Deserialization of Untrusted Data' + references: + - https://yaml.readthedocs.io/en/latest/basicuse.html?highlight=typ + category: security + technology: + - ruamel.yaml + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: MEDIUM + languages: + - python + message: >- + Avoid using unsafe `ruamel.yaml.YAML()`. `ruamel.yaml.YAML` can + create arbitrary Python objects. A malicious actor could exploit + this to run arbitrary code. Use `YAML(typ='rt')` or + `YAML(typ='safe')` instead. + severity: ERROR + pattern-either: + - pattern: ruamel.yaml.YAML(..., typ='unsafe', ...) + - pattern: ruamel.yaml.YAML(..., typ='base', ...) +- id: python.lang.security.deserialization.pickle.avoid-pickle + metadata: + owasp: + - A08:2017 - Insecure Deserialization + - A08:2021 - Software and Data Integrity Failures + cwe: + - 'CWE-502: Deserialization of Untrusted Data' + references: + - https://docs.python.org/3/library/pickle.html + category: security + technology: + - python + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + languages: + - python + message: >- + Avoid using `pickle`, which is known to lead to code execution vulnerabilities. + When unpickling, the serialized data could be manipulated to run arbitrary code. + Instead, consider serializing the relevant data as JSON or a similar text-based + serialization format. + severity: WARNING + patterns: + - pattern-either: + - pattern: pickle.$FUNC(...) + - pattern: _pickle.$FUNC(...) + - pattern-not: pickle.$FUNC("...") + - pattern-not: _pickle.$FUNC("...") +- id: python.lang.security.deserialization.pickle.avoid-cpickle + metadata: + owasp: + - A08:2017 - Insecure Deserialization + - A08:2021 - Software and Data Integrity Failures + cwe: + - 'CWE-502: Deserialization of Untrusted Data' + references: + - https://docs.python.org/3/library/pickle.html + category: security + technology: + - python + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + languages: + - python + message: >- + Avoid using `cPickle`, which is known to lead to code execution vulnerabilities. + When unpickling, the serialized data could be manipulated to run arbitrary code. + Instead, consider serializing the relevant data as JSON or a similar text-based + serialization format. + severity: WARNING + patterns: + - pattern: cPickle.$FUNC(...) + - pattern-not: cPickle.$FUNC("...") +- id: python.lang.security.deserialization.pickle.avoid-dill + metadata: + owasp: + - A08:2017 - Insecure Deserialization + - A08:2021 - Software and Data Integrity Failures + cwe: + - 'CWE-502: Deserialization of Untrusted Data' + references: + - https://docs.python.org/3/library/pickle.html + category: security + technology: + - python + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + languages: + - python + message: >- + Avoid using `dill`, which uses `pickle`, which is known to lead to code execution + vulnerabilities. + When unpickling, the serialized data could be manipulated to run arbitrary code. + Instead, consider serializing the relevant data as JSON or a similar text-based + serialization format. + severity: WARNING + patterns: + - pattern: dill.$FUNC(...) + - pattern-not: dill.$FUNC("...") +- id: python.lang.security.deserialization.pickle.avoid-shelve + metadata: + owasp: + - A08:2017 - Insecure Deserialization + - A08:2021 - Software and Data Integrity Failures + cwe: + - 'CWE-502: Deserialization of Untrusted Data' + references: + - https://docs.python.org/3/library/pickle.html + category: security + technology: + - python + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: MEDIUM + languages: + - python + message: >- + Avoid using `shelve`, which uses `pickle`, which is known to lead to code execution + vulnerabilities. + When unpickling, the serialized data could be manipulated to run arbitrary code. + Instead, consider serializing the relevant data as JSON or a similar text-based + serialization format. + severity: WARNING + pattern: shelve.$FUNC(...) +- id: python.lang.security.insecure-hash-algorithms-md5.insecure-hash-algorithm-md5 + patterns: + - pattern: hashlib.md5(...) + - pattern-not: hashlib.md5(..., usedforsecurity=False, ...) + message: >- + Detected MD5 hash algorithm which is considered insecure. MD5 is not + collision resistant and is therefore not suitable as a cryptographic + signature. Use SHA256 or SHA3 instead. + metadata: + source-rule-url: https://github.com/PyCQA/bandit/blob/d5f8fa0d89d7b11442fc6ec80ca42953974354c8/bandit/blacklists/calls.py#L59 + cwe: + - 'CWE-327: Use of a Broken or Risky Cryptographic Algorithm' + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + bandit-code: B303 + asvs: + section: V6 Stored Cryptography Verification Requirements + control_id: 6.2.2 Insecure Custom Algorithm + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x14-V6-Cryptography.md#v62-algorithms + version: '4' + references: + - https://www.schneier.com/blog/archives/2012/10/when_will_we_se.html + - https://www.trendmicro.com/vinfo/us/security/news/vulnerabilities-and-exploits/sha-1-collision-signals-the-end-of-the-algorithm-s-viability + - http://2012.sharcs.org/slides/stevens.pdf + - https://pycryptodome.readthedocs.io/en/latest/src/hash/sha3_256.html + category: security + technology: + - python + subcategory: + - vuln + likelihood: LOW + impact: MEDIUM + confidence: MEDIUM + severity: WARNING + languages: + - python +- id: python.lang.security.insecure-hash-algorithms.insecure-hash-algorithm-sha1 + pattern: hashlib.sha1(...) + fix-regex: + regex: sha1 + replacement: sha256 + message: >- + Detected SHA1 hash algorithm which is considered insecure. SHA1 is not + collision resistant and is therefore not suitable as a cryptographic + signature. Use SHA256 or SHA3 instead. + metadata: + source-rule-url: https://github.com/PyCQA/bandit/blob/d5f8fa0d89d7b11442fc6ec80ca42953974354c8/bandit/blacklists/calls.py#L59 + cwe: + - 'CWE-327: Use of a Broken or Risky Cryptographic Algorithm' + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + bandit-code: B303 + asvs: + section: V6 Stored Cryptography Verification Requirements + control_id: 6.2.2 Insecure Custom Algorithm + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x14-V6-Cryptography.md#v62-algorithms + version: '4' + references: + - https://www.schneier.com/blog/archives/2012/10/when_will_we_se.html + - https://www.trendmicro.com/vinfo/us/security/news/vulnerabilities-and-exploits/sha-1-collision-signals-the-end-of-the-algorithm-s-viability + - http://2012.sharcs.org/slides/stevens.pdf + - https://pycryptodome.readthedocs.io/en/latest/src/hash/sha3_256.html + category: security + technology: + - python + subcategory: + - vuln + likelihood: LOW + impact: MEDIUM + confidence: MEDIUM + severity: WARNING + languages: + - python +- id: python.lang.security.insecure-hash-function.insecure-hash-function + message: >- + Detected use of an insecure MD4 or MD5 hash function. + These functions have known vulnerabilities and are considered deprecated. + Consider using 'SHA256' or a similar function instead. + metadata: + cwe: + - 'CWE-327: Use of a Broken or Risky Cryptographic Algorithm' + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + source-rule-url: https://github.com/PyCQA/bandit/blob/b1411bfb43795d3ffd268bef17a839dee954c2b1/bandit/plugins/hashlib_new_insecure_functions.py + asvs: + section: V6 Stored Cryptography Verification Requirements + control_id: 6.2.2 Insecure Custom Algorithm + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x14-V6-Cryptography.md#v62-algorithms + version: '4' + references: + - https://tools.ietf.org/html/rfc6151 + - https://crypto.stackexchange.com/questions/44151/how-does-the-flame-malware-take-advantage-of-md5-collision + - https://pycryptodome.readthedocs.io/en/latest/src/hash/sha3_256.html + category: security + technology: + - python + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: MEDIUM + languages: [python] + severity: WARNING + pattern-either: + - pattern: hashlib.new("=~/[M|m][D|d][4|5]/", ...) + - pattern: hashlib.new(..., name="=~/[M|m][D|d][4|5]/", ...) +- id: python.lang.security.unverified-ssl-context.unverified-ssl-context + patterns: + - pattern-either: + - pattern: ssl._create_unverified_context(...) + - pattern: ssl._create_default_https_context = ssl._create_unverified_context + fix-regex: + regex: _create_unverified_context + replacement: create_default_context + message: >- + Unverified SSL context detected. This will permit insecure connections without + verifying + SSL certificates. Use 'ssl.create_default_context' instead. + metadata: + owasp: + - A03:2017 - Sensitive Data Exposure + - A07:2021 - Identification and Authentication Failures + cwe: + - 'CWE-295: Improper Certificate Validation' + references: + - https://docs.python.org/3/library/ssl.html#ssl-security + - https://docs.python.org/3/library/http.client.html#http.client.HTTPSConnection + category: security + technology: + - python + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: MEDIUM + severity: ERROR + languages: + - python +- id: python.lang.security.use-defused-xml-parse.use-defused-xml-parse + metadata: + owasp: + - A04:2017 - XML External Entities (XXE) + - A05:2021 - Security Misconfiguration + cwe: + - 'CWE-611: Improper Restriction of XML External Entity Reference' + references: + - https://docs.python.org/3/library/xml.html + - https://github.com/tiran/defusedxml + - https://owasp.org/www-community/vulnerabilities/XML_External_Entity_(XXE)_Processing + category: security + technology: + - python + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: LOW + impact: MEDIUM + confidence: MEDIUM + message: >- + The native Python `xml` library is vulnerable to XML External Entity (XXE) attacks. + These attacks can leak confidential data and "XML bombs" can cause denial of service. + Do not use this library to parse untrusted input. Instead + the Python documentation recommends using `defusedxml`. + languages: [python] + severity: ERROR + patterns: + - pattern: xml.etree.ElementTree.parse($...ARGS) + - pattern-not: xml.etree.ElementTree.parse("...") + fix: defusedxml.etree.ElementTree.parse($...ARGS) +- id: python.lang.security.use-defused-xml.use-defused-xml + metadata: + owasp: + - A04:2017 - XML External Entities (XXE) + - A05:2021 - Security Misconfiguration + cwe: + - 'CWE-611: Improper Restriction of XML External Entity Reference' + references: + - https://docs.python.org/3/library/xml.html + - https://github.com/tiran/defusedxml + - https://owasp.org/www-community/vulnerabilities/XML_External_Entity_(XXE)_Processing + category: security + technology: + - python + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + message: >- + The Python documentation recommends using `defusedxml` instead of `xml` because the native Python + `xml` library is vulnerable to XML External Entity (XXE) attacks. These attacks can leak confidential + data and "XML bombs" can cause denial of service. + languages: [python] + severity: ERROR + pattern: import xml +- id: python.lang.security.use-defused-xmlrpc.use-defused-xmlrpc + pattern-either: + - pattern: import xmlrpclib + - pattern: import SimpleXMLRPCServer + - pattern: import xmlrpc + message: >- + Detected use of xmlrpc. xmlrpc is not inherently safe from vulnerabilities. + Use defusedxml.xmlrpc instead. + metadata: + cwe: + - "CWE-776: Improper Restriction of Recursive Entity References in DTDs ('XML Entity Expansion')" + owasp: + - A04:2017 - XML External Entities (XXE) + - A05:2021 - Security Misconfiguration + source-rule-url: https://github.com/PyCQA/bandit/blob/07f84cb5f5e7c1055e6feaa0fe93afa471de0ac3/bandit/blacklists/imports.py#L160 + references: + - https://pypi.org/project/defusedxml/ + - https://docs.python.org/3/library/xml.html#xml-vulnerabilities + category: security + technology: + - python + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + severity: ERROR + languages: + - python +- id: python.lang.security.use-defusedcsv.use-defusedcsv + patterns: + - pattern: csv.writer(...) + - pattern-not: defusedcsv.writer(...) + message: >- + Detected the generation of a CSV file using the built-in `csv` module. + If user data is used to generate the data in this file, it is possible that + an attacker could inject a formula when the CSV is imported into a spreadsheet + application that runs an attacker script, which could steal data from the importing + user or, at worst, install malware on the user's computer. `defusedcsv` is a + drop-in replacement with the same API that will attempt to mitigate formula + injection attempts. You can use `defusedcsv` instead of `csv` to safely generate CSVs. + metadata: + cwe: + - 'CWE-1236: Improper Neutralization of Formula Elements in a CSV File' + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + references: + - https://github.com/raphaelm/defusedcsv + - https://owasp.org/www-community/attacks/CSV_Injection + - https://web.archive.org/web/20220516052229/https://www.contextis.com/us/blog/comma-separated-vulnerabilities + category: security + technology: + - python + confidence: LOW + subcategory: + - audit + likelihood: LOW + impact: LOW + fix-regex: + regex: csv + replacement: defusedcsv + languages: [python] + severity: INFO +- id: python.pycryptodome.security.insecure-cipher-algorithm-blowfish.insecure-cipher-algorithm-blowfish + message: >- + Detected Blowfish cipher algorithm which is considered insecure. This algorithm + is not cryptographically secure and can be reversed easily. Use AES instead. + metadata: + source-rule-url: https://github.com/PyCQA/bandit/blob/d5f8fa0d89d7b11442fc6ec80ca42953974354c8/bandit/blacklists/calls.py#L84 + cwe: + - 'CWE-327: Use of a Broken or Risky Cryptographic Algorithm' + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + bandit-code: B304 + references: + - https://stackoverflow.com/questions/1135186/whats-wrong-with-xor-encryption + category: security + technology: + - pycryptodome + subcategory: + - vuln + likelihood: LOW + impact: MEDIUM + confidence: MEDIUM + severity: WARNING + languages: + - python + pattern-either: + - pattern: Cryptodome.Cipher.Blowfish.new(...) + - pattern: Crypto.Cipher.Blowfish.new(...) +- id: python.pycryptodome.security.insecure-cipher-algorithm-des.insecure-cipher-algorithm-des + message: >- + Detected DES cipher algorithm which is considered insecure. This algorithm + is not cryptographically secure and can be reversed easily. Use AES instead. + metadata: + source-rule-url: https://github.com/PyCQA/bandit/blob/d5f8fa0d89d7b11442fc6ec80ca42953974354c8/bandit/blacklists/calls.py#L84 + cwe: + - 'CWE-327: Use of a Broken or Risky Cryptographic Algorithm' + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + bandit-code: B304 + references: + - https://cwe.mitre.org/data/definitions/326.html + category: security + technology: + - pycryptodome + subcategory: + - vuln + likelihood: LOW + impact: MEDIUM + confidence: MEDIUM + severity: WARNING + languages: + - python + pattern-either: + - pattern: Cryptodome.Cipher.DES.new(...) + - pattern: Crypto.Cipher.DES.new(...) +- id: python.pycryptodome.security.insecure-cipher-algorithm-rc2.insecure-cipher-algorithm-rc2 + message: >- + Detected RC2 cipher algorithm which is considered insecure. This algorithm + is not cryptographically secure and can be reversed easily. Use AES instead. + metadata: + source-rule-url: https://github.com/PyCQA/bandit/blob/d5f8fa0d89d7b11442fc6ec80ca42953974354c8/bandit/blacklists/calls.py#L84 + cwe: + - 'CWE-327: Use of a Broken or Risky Cryptographic Algorithm' + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + bandit-code: B304 + references: + - https://cwe.mitre.org/data/definitions/326.html + category: security + technology: + - pycryptodome + subcategory: + - vuln + likelihood: LOW + impact: MEDIUM + confidence: MEDIUM + severity: WARNING + languages: + - python + pattern-either: + - pattern: Cryptodome.Cipher.ARC2.new(...) + - pattern: Crypto.Cipher.ARC2.new(...) +- id: python.pycryptodome.security.insecure-cipher-algorithm-rc4.insecure-cipher-algorithm-rc4 + message: >- + Detected ARC4 cipher algorithm which is considered insecure. This algorithm + is not cryptographically secure and can be reversed easily. Use AES instead. + metadata: + source-rule-url: https://github.com/PyCQA/bandit/blob/d5f8fa0d89d7b11442fc6ec80ca42953974354c8/bandit/blacklists/calls.py#L84 + cwe: + - 'CWE-327: Use of a Broken or Risky Cryptographic Algorithm' + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + bandit-code: B304 + references: + - https://cwe.mitre.org/data/definitions/326.html + category: security + technology: + - pycryptodome + subcategory: + - vuln + likelihood: LOW + impact: MEDIUM + confidence: MEDIUM + severity: WARNING + languages: + - python + pattern-either: + - pattern: Cryptodome.Cipher.ARC4.new(...) + - pattern: Crypto.Cipher.ARC4.new(...) +- id: python.pycryptodome.security.insecure-cipher-algorithm.insecure-cipher-algorithm-xor + message: >- + Detected XOR cipher algorithm which is considered insecure. This algorithm + is not cryptographically secure and can be reversed easily. Use AES instead. + metadata: + source-rule-url: https://github.com/PyCQA/bandit/blob/d5f8fa0d89d7b11442fc6ec80ca42953974354c8/bandit/blacklists/calls.py#L84 + cwe: + - 'CWE-327: Use of a Broken or Risky Cryptographic Algorithm' + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + bandit-code: B304 + references: + - https://stackoverflow.com/questions/1135186/whats-wrong-with-xor-encryption + category: security + technology: + - pycryptodome + subcategory: + - vuln + likelihood: LOW + impact: MEDIUM + confidence: MEDIUM + severity: WARNING + languages: + - python + pattern-either: + - pattern: Cryptodome.Cipher.XOR.new(...) + - pattern: Crypto.Cipher.XOR.new(...) +- id: python.pycryptodome.security.insecure-hash-algorithm-md2.insecure-hash-algorithm-md2 + message: >- + Detected MD2 hash algorithm which is considered insecure. MD2 is not + collision resistant and is therefore not suitable as a cryptographic + signature. Use SHA256 or SHA3 instead. + metadata: + source-rule-url: https://github.com/PyCQA/bandit/blob/d5f8fa0d89d7b11442fc6ec80ca42953974354c8/bandit/blacklists/calls.py#L59 + cwe: + - 'CWE-327: Use of a Broken or Risky Cryptographic Algorithm' + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + references: + - https://www.schneier.com/blog/archives/2012/10/when_will_we_se.html + - https://www.trendmicro.com/vinfo/us/security/news/vulnerabilities-and-exploits/sha-1-collision-signals-the-end-of-the-algorithm-s-viability + - http://2012.sharcs.org/slides/stevens.pdf + - https://pycryptodome.readthedocs.io/en/latest/src/hash/sha3_256.html + category: security + technology: + - pycryptodome + subcategory: + - vuln + likelihood: LOW + impact: MEDIUM + confidence: MEDIUM + severity: WARNING + languages: + - python + pattern-either: + - pattern: Crypto.Hash.MD2.new(...) + - pattern: Cryptodome.Hash.MD2.new (...) +- id: python.pycryptodome.security.insecure-hash-algorithm-md4.insecure-hash-algorithm-md4 + message: >- + Detected MD4 hash algorithm which is considered insecure. MD4 is not + collision resistant and is therefore not suitable as a cryptographic + signature. Use SHA256 or SHA3 instead. + metadata: + source-rule-url: https://github.com/PyCQA/bandit/blob/d5f8fa0d89d7b11442fc6ec80ca42953974354c8/bandit/blacklists/calls.py#L59 + cwe: + - 'CWE-327: Use of a Broken or Risky Cryptographic Algorithm' + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + references: + - https://www.schneier.com/blog/archives/2012/10/when_will_we_se.html + - https://www.trendmicro.com/vinfo/us/security/news/vulnerabilities-and-exploits/sha-1-collision-signals-the-end-of-the-algorithm-s-viability + - http://2012.sharcs.org/slides/stevens.pdf + - https://pycryptodome.readthedocs.io/en/latest/src/hash/sha3_256.html + category: security + technology: + - pycryptodome + subcategory: + - vuln + likelihood: LOW + impact: MEDIUM + confidence: MEDIUM + severity: WARNING + languages: + - python + pattern-either: + - pattern: Crypto.Hash.MD4.new(...) + - pattern: Cryptodome.Hash.MD4.new (...) +- id: python.pycryptodome.security.insecure-hash-algorithm-md5.insecure-hash-algorithm-md5 + message: >- + Detected MD5 hash algorithm which is considered insecure. MD5 is not + collision resistant and is therefore not suitable as a cryptographic + signature. Use SHA256 or SHA3 instead. + metadata: + source-rule-url: https://github.com/PyCQA/bandit/blob/d5f8fa0d89d7b11442fc6ec80ca42953974354c8/bandit/blacklists/calls.py#L59 + cwe: + - 'CWE-327: Use of a Broken or Risky Cryptographic Algorithm' + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + references: + - https://www.schneier.com/blog/archives/2012/10/when_will_we_se.html + - https://www.trendmicro.com/vinfo/us/security/news/vulnerabilities-and-exploits/sha-1-collision-signals-the-end-of-the-algorithm-s-viability + - http://2012.sharcs.org/slides/stevens.pdf + - https://pycryptodome.readthedocs.io/en/latest/src/hash/sha3_256.html + category: security + technology: + - pycryptodome + subcategory: + - vuln + likelihood: LOW + impact: MEDIUM + confidence: MEDIUM + severity: WARNING + languages: + - python + pattern-either: + - pattern: Crypto.Hash.MD5.new(...) + - pattern: Cryptodome.Hash.MD5.new (...) +- id: python.pycryptodome.security.insecure-hash-algorithm.insecure-hash-algorithm-sha1 + message: >- + Detected SHA1 hash algorithm which is considered insecure. SHA1 is not + collision resistant and is therefore not suitable as a cryptographic + signature. Use SHA256 or SHA3 instead. + metadata: + source-rule-url: https://github.com/PyCQA/bandit/blob/d5f8fa0d89d7b11442fc6ec80ca42953974354c8/bandit/blacklists/calls.py#L59 + cwe: + - 'CWE-327: Use of a Broken or Risky Cryptographic Algorithm' + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + references: + - https://www.schneier.com/blog/archives/2012/10/when_will_we_se.html + - https://www.trendmicro.com/vinfo/us/security/news/vulnerabilities-and-exploits/sha-1-collision-signals-the-end-of-the-algorithm-s-viability + - http://2012.sharcs.org/slides/stevens.pdf + - https://pycryptodome.readthedocs.io/en/latest/src/hash/sha3_256.html + category: security + technology: + - pycryptodome + subcategory: + - vuln + likelihood: LOW + impact: MEDIUM + confidence: MEDIUM + severity: WARNING + languages: + - python + pattern-either: + - pattern: Crypto.Hash.SHA.new(...) + - pattern: Cryptodome.Hash.SHA.new (...) +- id: python.pycryptodome.security.insufficient-dsa-key-size.insufficient-dsa-key-size + patterns: + - pattern-either: + - pattern: Crypto.PublicKey.DSA.generate(..., bits=$SIZE, ...) + - pattern: Crypto.PublicKey.DSA.generate($SIZE, ...) + - pattern: Cryptodome.PublicKey.DSA.generate(..., bits=$SIZE, ...) + - pattern: Cryptodome.PublicKey.DSA.generate($SIZE, ...) + - metavariable-comparison: + metavariable: $SIZE + comparison: $SIZE < 2048 + message: >- + Detected an insufficient key size for DSA. NIST recommends + a key size of 2048 or higher. + metadata: + cwe: + - 'CWE-326: Inadequate Encryption Strength' + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + source-rule-url: https://github.com/PyCQA/bandit/blob/b1411bfb43795d3ffd268bef17a839dee954c2b1/bandit/plugins/weak_cryptographic_key.py + references: + - https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-57Pt3r1.pdf + category: security + technology: + - pycryptodome + subcategory: + - vuln + likelihood: LOW + impact: MEDIUM + confidence: MEDIUM + languages: [python] + severity: WARNING +- id: python.pycryptodome.security.insufficient-rsa-key-size.insufficient-rsa-key-size + patterns: + - pattern-either: + - pattern: Crypto.PublicKey.RSA.generate(..., bits=$SIZE, ...) + - pattern: Crypto.PublicKey.RSA.generate($SIZE, ...) + - pattern: Cryptodome.PublicKey.RSA.generate(..., bits=$SIZE, ...) + - pattern: Cryptodome.PublicKey.RSA.generate($SIZE, ...) + - metavariable-comparison: + metavariable: $SIZE + comparison: $SIZE < 2048 + message: >- + Detected an insufficient key size for RSA. NIST recommends + a key size of 2048 or higher. + metadata: + cwe: + - 'CWE-326: Inadequate Encryption Strength' + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + source-rule-url: https://github.com/PyCQA/bandit/blob/b1411bfb43795d3ffd268bef17a839dee954c2b1/bandit/plugins/weak_cryptographic_key.py + references: + - https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-57Pt3r1.pdf + category: security + technology: + - pycryptodome + subcategory: + - vuln + likelihood: LOW + impact: MEDIUM + confidence: MEDIUM + languages: [python] + severity: WARNING +- id: python.pycryptodome.security.mode-without-authentication.crypto-mode-without-authentication + message: >- + An encryption mode of operation is being used without proper message authentication. This can potentially + result in the encrypted content to be decrypted by an attacker. Consider instead use an AEAD mode + of operation like GCM. + languages: + - python + severity: ERROR + metadata: + category: security + technology: + - cryptography + cwe: + - 'CWE-327: Use of a Broken or Risky Cryptographic Algorithm' + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - vuln + likelihood: LOW + impact: MEDIUM + confidence: MEDIUM + patterns: + - pattern-either: + - patterns: + - pattern-either: + - pattern: | + AES.new(..., $PYCRYPTODOME_MODE) + - pattern-not-inside: | + AES.new(..., $PYCRYPTODOME_MODE) + ... + HMAC.new + - metavariable-pattern: + metavariable: $PYCRYPTODOME_MODE + patterns: + - pattern-either: + - pattern: AES.MODE_CBC + - pattern: AES.MODE_CTR + - pattern: AES.MODE_CFB + - pattern: AES.MODE_OFB +- id: python.pymongo.security.mongodb.mongo-client-bad-auth + pattern: | + pymongo.MongoClient(..., authMechanism='MONGODB-CR') + message: >- + Warning MONGODB-CR was deprecated with the release of MongoDB 3.6 and is no longer supported by MongoDB + 4.0 (see https://api.mongodb.com/python/current/examples/authentication.html for details). + fix-regex: + regex: MONGODB-CR + replacement: SCRAM-SHA-256 + severity: WARNING + languages: + - python + metadata: + cwe: + - 'CWE-477: Use of Obsolete Function' + category: security + technology: + - pymongo + references: + - https://cwe.mitre.org/data/definitions/477.html + subcategory: + - vuln + likelihood: LOW + impact: LOW + confidence: MEDIUM +- id: python.pyramid.audit.authtkt-cookie-httponly-unsafe-default.pyramid-authtkt-cookie-httponly-unsafe-default + patterns: + - pattern: pyramid.authentication.$FUNC($...PARAMS) + - metavariable-pattern: + metavariable: $FUNC + pattern-either: + - pattern: AuthTktCookieHelper + - pattern: AuthTktAuthenticationPolicy + - pattern-not: pyramid.authentication.$FUNC(..., httponly=$HTTPONLY, ...) + - pattern-not: pyramid.authentication.$FUNC(..., **$PARAMS, ...) + - focus-metavariable: $...PARAMS + fix: | + $...PARAMS, httponly=True + message: >- + Found a Pyramid Authentication Ticket cookie without the httponly option correctly set. Pyramid + cookies should be handled securely by setting httponly=True. + If this parameter is not properly set, your cookies are not properly protected and + are at risk of being stolen by an attacker. + metadata: + cwe: + - "CWE-1004: Sensitive Cookie Without 'HttpOnly' Flag" + owasp: + - A05:2021 - Security Misconfiguration + category: security + technology: + - pyramid + references: + - https://owasp.org/Top10/A05_2021-Security_Misconfiguration + subcategory: + - vuln + likelihood: LOW + impact: LOW + confidence: MEDIUM + languages: [python] + severity: WARNING +- id: python.pyramid.audit.authtkt-cookie-httponly-unsafe-value.pyramid-authtkt-cookie-httponly-unsafe-value + patterns: + - pattern-either: + - patterns: + - pattern-not: pyramid.authentication.AuthTktCookieHelper(..., **$PARAMS) + - pattern: pyramid.authentication.AuthTktCookieHelper(..., httponly=$HTTPONLY, ...) + - patterns: + - pattern-not: pyramid.authentication.AuthTktAuthenticationPolicy(..., **$PARAMS) + - pattern: pyramid.authentication.AuthTktAuthenticationPolicy(..., httponly=$HTTPONLY, ...) + - pattern: $HTTPONLY + - metavariable-pattern: + metavariable: $HTTPONLY + pattern: | + False + fix: | + True + message: >- + Found a Pyramid Authentication Ticket cookie without the httponly option correctly set. Pyramid + cookies should be handled securely by setting httponly=True. + If this parameter is not properly set, your cookies are not properly protected and + are at risk of being stolen by an attacker. + metadata: + cwe: + - "CWE-1004: Sensitive Cookie Without 'HttpOnly' Flag" + owasp: + - A05:2021 - Security Misconfiguration + category: security + technology: + - pyramid + references: + - https://owasp.org/Top10/A05_2021-Security_Misconfiguration + subcategory: + - vuln + likelihood: LOW + impact: LOW + confidence: MEDIUM + languages: [python] + severity: WARNING +- id: python.pyramid.audit.authtkt-cookie-samesite.pyramid-authtkt-cookie-samesite + patterns: + - pattern-either: + - pattern: pyramid.authentication.AuthTktCookieHelper(..., samesite=$SAMESITE, ...) + - pattern: pyramid.authentication.AuthTktAuthenticationPolicy(..., samesite=$SAMESITE, ...) + - pattern: $SAMESITE + - metavariable-regex: + metavariable: $SAMESITE + regex: (?!'Lax') + fix: | + 'Lax' + message: >- + Found a Pyramid Authentication Ticket without the samesite option correctly set. Pyramid + cookies should be handled securely by setting samesite='Lax'. + If this parameter is not properly set, your cookies are not properly protected and + are at risk of being stolen by an attacker. + metadata: + cwe: + - 'CWE-1275: Sensitive Cookie with Improper SameSite Attribute' + owasp: + - A01:2021 - Broken Access Control + category: security + technology: + - pyramid + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - vuln + likelihood: LOW + impact: LOW + confidence: MEDIUM + languages: [python] + severity: WARNING +- id: python.pyramid.audit.authtkt-cookie-secure-unsafe-default.pyramid-authtkt-cookie-secure-unsafe-default + patterns: + - pattern-either: + - patterns: + - pattern-not: pyramid.authentication.AuthTktCookieHelper(..., secure=$SECURE, ...) + - pattern-not: pyramid.authentication.AuthTktCookieHelper(..., **$PARAMS) + - pattern: pyramid.authentication.AuthTktCookieHelper(...) + - patterns: + - pattern-not: pyramid.authentication.AuthTktAuthenticationPolicy(..., secure=$SECURE, ...) + - pattern-not: pyramid.authentication.AuthTktAuthenticationPolicy(..., **$PARAMS) + - pattern: pyramid.authentication.AuthTktAuthenticationPolicy(...) + fix-regex: + regex: (.*)\) + replacement: \1, secure=True) + message: >- + Found a Pyramid Authentication Ticket cookie using an unsafe default for the secure option. + Pyramid cookies should be handled securely by setting secure=True. + If this parameter is not properly set, your cookies are not properly protected and + are at risk of being stolen by an attacker. + metadata: + cwe: + - "CWE-614: Sensitive Cookie in HTTPS Session Without 'Secure' Attribute" + owasp: + - A05:2021 - Security Misconfiguration + category: security + technology: + - pyramid + references: + - https://owasp.org/Top10/A05_2021-Security_Misconfiguration + subcategory: + - vuln + likelihood: LOW + impact: LOW + confidence: MEDIUM + languages: [python] + severity: WARNING +- id: python.pyramid.audit.authtkt-cookie-secure-unsafe-value.pyramid-authtkt-cookie-secure-unsafe-value + patterns: + - pattern-either: + - patterns: + - pattern-not: pyramid.authentication.AuthTktCookieHelper(..., **$PARAMS) + - pattern: pyramid.authentication.AuthTktCookieHelper(..., secure=$SECURE, ...) + - patterns: + - pattern-not: pyramid.authentication.AuthTktAuthenticationPolicy(..., **$PARAMS) + - pattern: pyramid.authentication.AuthTktAuthenticationPolicy(..., secure=$SECURE, ...) + - pattern: $SECURE + - metavariable-pattern: + metavariable: $SECURE + pattern: | + False + fix: | + True + message: >- + Found a Pyramid Authentication Ticket cookie without the secure option correctly set. Pyramid + cookies should be handled securely by setting secure=True. + If this parameter is not properly set, your cookies are not properly protected and + are at risk of being stolen by an attacker. + metadata: + cwe: + - "CWE-614: Sensitive Cookie in HTTPS Session Without 'Secure' Attribute" + owasp: + - A05:2021 - Security Misconfiguration + category: security + technology: + - pyramid + references: + - https://owasp.org/Top10/A05_2021-Security_Misconfiguration + subcategory: + - vuln + likelihood: LOW + impact: LOW + confidence: MEDIUM + languages: [python] + severity: WARNING +- id: python.pyramid.audit.csrf-check-disabled.pyramid-csrf-check-disabled + message: CSRF protection is disabled for this view. This is a security risk. + metadata: + cwe: + - 'CWE-352: Cross-Site Request Forgery (CSRF)' + owasp: + - A01:2021 - Broken Access Control + asvs: + section: V4 Access Control + control_id: 4.2.2 CSRF + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x12-V4-Access-Control.md#v42-operation-level-access-control + version: '4' + category: security + technology: + - pyramid + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + severity: WARNING + languages: + - python + patterns: + - pattern-inside: | + from pyramid.view import view_config + ... + @view_config(..., require_csrf=$REQUIRE_CSRF, ...) + def $VIEW(...): + ... + - pattern: $REQUIRE_CSRF + - metavariable-comparison: + metavariable: $REQUIRE_CSRF + comparison: $REQUIRE_CSRF == False + fix: | + True +- id: python.pyramid.audit.csrf-origin-check-disabled-globally.pyramid-csrf-origin-check-disabled-globally + patterns: + - pattern-inside: | + $CONFIG.set_default_csrf_options(..., check_origin=$CHECK_ORIGIN, ...) + - pattern: $CHECK_ORIGIN + - metavariable-comparison: + metavariable: $CHECK_ORIGIN + comparison: $CHECK_ORIGIN == False + message: >- + Automatic check of the referrer for cross-site request forgery tokens has been explicitly disabled + globally, + which might leave views unprotected when an unsafe CSRF storage policy is used. + Use 'pyramid.config.Configurator.set_default_csrf_options(check_origin=True)' to turn the automatic + check for all unsafe methods (per RFC2616). + languages: [python] + severity: ERROR + fix: | + True + metadata: + cwe: + - 'CWE-352: Cross-Site Request Forgery (CSRF)' + owasp: + - A01:2021 - Broken Access Control + category: security + technology: + - pyramid + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: LOW + impact: LOW + confidence: MEDIUM +- id: python.pyramid.audit.csrf-origin-check-disabled.pyramid-csrf-origin-check-disabled + message: >- + Origin check for the CSRF token is disabled for this view. + This might represent a security risk if the CSRF storage policy is not known to be secure. + metadata: + cwe: + - 'CWE-352: Cross-Site Request Forgery (CSRF)' + owasp: + - A01:2021 - Broken Access Control + asvs: + section: V4 Access Control + control_id: 4.2.2 CSRF + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x12-V4-Access-Control.md#v42-operation-level-access-control + version: '4' + category: security + technology: + - pyramid + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: LOW + impact: LOW + confidence: MEDIUM + severity: WARNING + languages: + - python + patterns: + - pattern-inside: | + from pyramid.view import view_config + ... + @view_config(..., check_origin=$CHECK_ORIGIN, ...) + def $VIEW(...): + ... + - pattern: $CHECK_ORIGIN + - metavariable-comparison: + metavariable: $CHECK_ORIGIN + comparison: $CHECK_ORIGIN == False + fix: | + True +- id: python.pyramid.audit.set-cookie-httponly-unsafe-default.pyramid-set-cookie-httponly-unsafe-default + patterns: + - pattern-either: + - pattern-inside: | + @pyramid.view.view_config(...) + def $VIEW($REQUEST): + ... + $RESPONSE = $REQUEST.response + ... + - pattern-inside: | + def $VIEW(...): + ... + $RESPONSE = pyramid.httpexceptions.HTTPFound(...) + ... + - pattern-not: $RESPONSE.set_cookie(..., httponly=$HTTPONLY, ...) + - pattern-not: $RESPONSE.set_cookie(..., **$PARAMS) + - pattern: $RESPONSE.set_cookie(...) + fix-regex: + regex: (.*)\) + replacement: \1, httponly=True) + message: >- + Found a Pyramid cookie using an unsafe default for the httponly option. + Pyramid cookies should be handled securely by setting httponly=True in response.set_cookie(...). + If this parameter is not properly set, your cookies are not properly protected and + are at risk of being stolen by an attacker. + metadata: + cwe: + - "CWE-1004: Sensitive Cookie Without 'HttpOnly' Flag" + owasp: + - A05:2021 - Security Misconfiguration + category: security + technology: + - pyramid + references: + - https://owasp.org/Top10/A05_2021-Security_Misconfiguration + subcategory: + - vuln + likelihood: LOW + impact: LOW + confidence: MEDIUM + languages: [python] + severity: WARNING +- id: python.pyramid.audit.set-cookie-httponly-unsafe-value.pyramid-set-cookie-httponly-unsafe-value + patterns: + - pattern-either: + - pattern-inside: | + @pyramid.view.view_config(...) + def $VIEW($REQUEST): + ... + $RESPONSE = $REQUEST.response + ... + - pattern-inside: | + def $VIEW(...): + ... + $RESPONSE = pyramid.httpexceptions.HTTPFound(...) + ... + - pattern-not: $RESPONSE.set_cookie(..., **$PARAMS) + - pattern: $RESPONSE.set_cookie(..., httponly=$HTTPONLY, ...) + - pattern: $HTTPONLY + - metavariable-pattern: + metavariable: $HTTPONLY + pattern: | + False + fix: | + True + message: >- + Found a Pyramid cookie without the httponly option correctly set. + Pyramid cookies should be handled securely by setting httponly=True in response.set_cookie(...). + If this parameter is not properly set, your cookies are not properly protected and + are at risk of being stolen by an attacker. + metadata: + cwe: + - "CWE-1004: Sensitive Cookie Without 'HttpOnly' Flag" + owasp: + - A05:2021 - Security Misconfiguration + references: + - https://owasp.org/www-community/controls/SecureCookieAttribute + - https://owasp.org/www-community/HttpOnly + - https://cheatsheetseries.owasp.org/cheatsheets/Session_Management_Cheat_Sheet.html#httponly-attribute + category: security + technology: + - pyramid + subcategory: + - vuln + likelihood: LOW + impact: LOW + confidence: MEDIUM + languages: [python] + severity: WARNING +- id: python.pyramid.audit.set-cookie-samesite-unsafe-default.pyramid-set-cookie-samesite-unsafe-default + patterns: + - pattern-either: + - pattern-inside: | + @pyramid.view.view_config(...) + def $VIEW($REQUEST): + ... + $RESPONSE = $REQUEST.response + ... + - pattern-inside: | + def $VIEW(...): + ... + $RESPONSE = pyramid.httpexceptions.HTTPFound(...) + ... + - pattern-not: $RESPONSE.set_cookie(..., samesite=$SAMESITE, ...) + - pattern-not: $RESPONSE.set_cookie(..., **$PARAMS) + - pattern: $RESPONSE.set_cookie(...) + fix-regex: + regex: (.*)\) + replacement: \1, samesite='Lax') + message: >- + Found a Pyramid cookie using an unsafe value for the samesite option. + Pyramid cookies should be handled securely by setting samesite='Lax' in response.set_cookie(...). + If this parameter is not properly set, your cookies are not properly protected and + are at risk of being stolen by an attacker. + metadata: + cwe: + - 'CWE-1275: Sensitive Cookie with Improper SameSite Attribute' + owasp: + - A01:2021 - Broken Access Control + category: security + technology: + - pyramid + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - vuln + likelihood: LOW + impact: LOW + confidence: MEDIUM + languages: [python] + severity: WARNING +- id: python.pyramid.audit.set-cookie-samesite-unsafe-value.pyramid-set-cookie-samesite-unsafe-value + patterns: + - pattern-either: + - pattern-inside: | + @pyramid.view.view_config(...) + def $VIEW($REQUEST): + ... + $RESPONSE = $REQUEST.response + ... + - pattern-inside: | + def $VIEW(...): + ... + $RESPONSE = pyramid.httpexceptions.HTTPFound(...) + ... + - pattern-not: $RESPONSE.set_cookie(..., **$PARAMS) + - pattern: $RESPONSE.set_cookie(..., samesite=$SAMESITE, ...) + - pattern: $SAMESITE + - metavariable-regex: + metavariable: $SAMESITE + regex: (?!'Lax') + fix: | + 'Lax' + message: >- + Found a Pyramid cookie without the samesite option correctly set. + Pyramid cookies should be handled securely by setting samesite='Lax' in response.set_cookie(...). + If this parameter is not properly set, your cookies are not properly protected and + are at risk of being stolen by an attacker. + metadata: + cwe: + - 'CWE-1275: Sensitive Cookie with Improper SameSite Attribute' + owasp: + - A01:2021 - Broken Access Control + category: security + technology: + - pyramid + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - vuln + likelihood: LOW + impact: LOW + confidence: MEDIUM + languages: [python] + severity: WARNING +- id: python.pyramid.audit.set-cookie-secure-unsafe-default.pyramid-set-cookie-secure-unsafe-default + patterns: + - pattern-either: + - pattern-inside: | + @pyramid.view.view_config(...) + def $VIEW($REQUEST): + ... + $RESPONSE = $REQUEST.response + ... + - pattern-inside: | + def $VIEW(...): + ... + $RESPONSE = pyramid.httpexceptions.HTTPFound(...) + ... + - pattern-not: $RESPONSE.set_cookie(..., secure=$SECURE, ...) + - pattern-not: $RESPONSE.set_cookie(..., **$PARAMS) + - pattern: $RESPONSE.set_cookie(...) + fix-regex: + regex: (.*)\) + replacement: \1, secure=True) + message: >- + Found a Pyramid cookie using an unsafe default for the secure option. + Pyramid cookies should be handled securely by setting secure=True in response.set_cookie(...). + If this parameter is not properly set, your cookies are not properly protected and + are at risk of being stolen by an attacker. + metadata: + cwe: + - "CWE-614: Sensitive Cookie in HTTPS Session Without 'Secure' Attribute" + owasp: + - A05:2021 - Security Misconfiguration + category: security + technology: + - pyramid + references: + - https://owasp.org/Top10/A05_2021-Security_Misconfiguration + subcategory: + - vuln + likelihood: LOW + impact: LOW + confidence: MEDIUM + languages: [python] + severity: WARNING +- id: python.pyramid.audit.set-cookie-secure-unsafe-value.pyramid-set-cookie-secure-unsafe-value + patterns: + - pattern-either: + - pattern-inside: | + @pyramid.view.view_config(...) + def $VIEW($REQUEST): + ... + $RESPONSE = $REQUEST.response + ... + - pattern-inside: | + def $VIEW(...): + ... + $RESPONSE = pyramid.httpexceptions.HTTPFound(...) + ... + - pattern-not: $RESPONSE.set_cookie(..., **$PARAMS) + - pattern: $RESPONSE.set_cookie(..., secure=$SECURE, ...) + - pattern: $SECURE + - metavariable-pattern: + metavariable: $SECURE + pattern: | + False + fix: | + True + message: >- + Found a Pyramid cookie without the secure option correctly set. + Pyramid cookies should be handled securely by setting secure=True in response.set_cookie(...). + If this parameter is not properly set, your cookies are not properly protected and + are at risk of being stolen by an attacker. + metadata: + cwe: + - "CWE-614: Sensitive Cookie in HTTPS Session Without 'Secure' Attribute" + owasp: + - A05:2021 - Security Misconfiguration + category: security + technology: + - pyramid + references: + - https://owasp.org/Top10/A05_2021-Security_Misconfiguration + subcategory: + - vuln + likelihood: LOW + impact: LOW + confidence: MEDIUM + languages: [python] + severity: WARNING +- id: python.pyramid.security.csrf-check-disabled-globally.pyramid-csrf-check-disabled-globally + patterns: + - pattern-inside: | + $CONFIG.set_default_csrf_options(..., require_csrf=$REQUIRE_CSRF, ...) + - pattern: $REQUIRE_CSRF + - metavariable-comparison: + metavariable: $REQUIRE_CSRF + comparison: $REQUIRE_CSRF == False + message: >- + Automatic check of cross-site request forgery tokens has been explicitly disabled globally, which + might leave views unprotected. + Use 'pyramid.config.Configurator.set_default_csrf_options(require_csrf=True)' to turn the automatic + check for all unsafe methods (per RFC2616). + languages: [python] + severity: ERROR + fix: | + True + metadata: + cwe: + - 'CWE-352: Cross-Site Request Forgery (CSRF)' + owasp: + - A01:2021 - Broken Access Control + category: security + technology: + - pyramid + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: LOW + impact: LOW + confidence: MEDIUM +- id: python.pyramid.security.direct-use-of-response.pyramid-direct-use-of-response + message: >- + Detected data rendered directly to the end user via 'Response'. + This bypasses Pyramid's built-in cross-site scripting + (XSS) defenses and could result in an XSS vulnerability. Use Pyramid's + template engines to safely render HTML. + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + category: security + technology: + - pyramid + references: + - https://owasp.org/Top10/A03_2021-Injection + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: LOW + impact: MEDIUM + confidence: MEDIUM + languages: + - python + severity: ERROR + mode: taint + pattern-sources: + - patterns: + - pattern-inside: | + @pyramid.view.view_config( ... ) + def $VIEW($REQ): + ... + - pattern: $REQ.$ANYTHING + - pattern-not: $REQ.dbsession + pattern-sinks: + - patterns: + - pattern-either: + - pattern: | + pyramid.request.Response.text($SINK) + - pattern: | + pyramid.request.Response($SINK) + - pattern: | + $REQ.response.body = $SINK + - pattern: | + $REQ.response.text = $SINK + - pattern: | + $REQ.response.ubody = $SINK + - pattern: | + $REQ.response.unicode_body = $SINK + - pattern: $SINK +- id: python.pyramid.security.sqlalchemy-sql-injection.pyramid-sqlalchemy-sql-injection + message: >- + Distinct, Having, Group_by, Order_by, and Filter in SQLAlchemy can + cause sql injections if the developer inputs raw SQL into the before-mentioned + clauses. This pattern captures relevant cases in which the developer inputs + raw SQL into the distinct, having, group_by, order_by or filter clauses and + injects user-input into the raw SQL with any function besides "bindparams". + Use bindParams to securely bind user-input to SQL statements. + languages: + - python + severity: ERROR + metadata: + category: security + cwe: + - "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')" + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + references: + - https://docs.sqlalchemy.org/en/14/tutorial/data_select.html#tutorial-selecting-data + technology: + - pyramid + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: HIGH + confidence: MEDIUM + mode: taint + pattern-sources: + - patterns: + - pattern-inside: | + from pyramid.view import view_config + ... + @view_config( ... ) + def $VIEW($REQ): + ... + - pattern: $REQ.$ANYTHING + - pattern-not: $REQ.dbsession + pattern-sinks: + - patterns: + - pattern-inside: | + $QUERY = $REQ.dbsession.query(...) + ... + - pattern-either: + - pattern: | + $QUERY.$SQLFUNC("...".$FORMATFUNC(..., $SINK, ...)) + - pattern: | + $QUERY.join(...).$SQLFUNC("...".$FORMATFUNC(..., $SINK, ...)) + - pattern: $SINK + - metavariable-regex: + metavariable: $SQLFUNC + regex: (group_by|order_by|distinct|having|filter) + - metavariable-regex: + metavariable: $FORMATFUNC + regex: (?!bindparams) + fix-regex: + regex: format + replacement: bindparams +- id: python.requests.best-practice.use-raise-for-status.use-raise-for-status + patterns: + - pattern-either: + - pattern: requests.request(...) + - pattern: requests.get(...) + - pattern: requests.post(...) + - pattern: requests.put(...) + - pattern: requests.delete(...) + - pattern: requests.head(...) + - pattern: requests.patch(...) + - pattern-not-inside: | + $RESP = requests.$METHOD(...) + $RESP.raise_for_status(...) + - pattern-not-inside: | + requests.$METHOD(...).raise_for_status(...) + - pattern-not-inside: | + $RESP = requests.$METHOD(...) + if $RESP.status_code == ...: + ... + - pattern-not-inside: | + $RESP = requests.$METHOD(...) + if $RESP.status_code != ...: + ... + - pattern-not-inside: | + $RESP = requests.$METHOD(...) + ... + if $RESP.ok: + ... + - pattern-not-inside: | + $RESP = requests.$METHOD(...) + ... + if not $RESP.ok: + ... + - pattern-not-inside: | + with ...: + ... + $RESP = requests.$METHOD(...) + ... + $RESP.raise_for_status(...) + - pattern-not-inside: | + with ... as ...: + ... + $RESP = requests.$METHOD(...) + ... + $RESP.raise_for_status(...) + message: >- + There's an HTTP request made with requests, + but the raise_for_status() utility method isn't used. + This can result in request errors going unnoticed + and your code behaving in unexpected ways, + such as if your authorization API returns a 500 error + while you're only checking for a 401. + metadata: + references: + - https://requests.readthedocs.io/en/master/api/#requests.Response.raise_for_status + category: best-practice + technology: + - requests + severity: WARNING + languages: + - python +- id: python.requests.best-practice.use-request-json-shortcut.python.requests.best-practice.use-request-json-shortcut + patterns: + - pattern-inside: import json; ... + - pattern-inside: import requests; ... + - pattern: requests.$METHOD(..., body=json.dumps($BODY), ...) + message: >- + The requests library has a convenient shortcut for sending JSON requests, + which lets you stop worrying about serializing the body yourself. + To use it, replace `body=json.dumps(...)` with `json=...`. + severity: WARNING + metadata: + references: + - https://requests.readthedocs.io/en/stable/user/quickstart/#more-complicated-post-requests + category: best-practice + technology: + - requests + languages: + - python +- id: python.requests.best-practice.use-response-json-shortcut.python.requests.best-practice.use-response-json-shortcut + patterns: + - pattern-inside: import json; ... + - pattern-inside: import requests; ... + - pattern-inside: $RESP = requests.$METHOD(...); ... + - pattern: json.loads($RESP.text) + fix: $RESP.json() + message: >- + The requests library has a convenient shortcut for reading JSON responses, + which lets you stop worrying about deserializing the response yourself. + severity: WARNING + metadata: + references: + - https://requests.readthedocs.io/en/stable/user/quickstart/#json-response-content + category: best-practice + technology: + - requests + languages: + - python +- id: python.requests.best-practice.use-timeout.use-timeout + pattern-either: + - patterns: + - pattern-not: requests.$W(..., timeout=$N, ...) + - pattern-not: requests.$W(..., **$KWARGS) + - pattern-either: + - pattern: requests.request(...) + - pattern: requests.get(...) + - pattern: requests.post(...) + - pattern: requests.put(...) + - pattern: requests.delete(...) + - pattern: requests.head(...) + - pattern: requests.patch(...) + - patterns: + - pattern-inside: | + $SESSION = requests.Session(...) + ... + - pattern-not: | + $SESSION.$W(..., timeout=$N, ...) + - pattern-not: | + $SESSION.$W(..., **$KWARGS) + - pattern-either: + - pattern: $SESSION.get(...) + - pattern: $SESSION.post(...) + - pattern: $SESSION.put(...) + - pattern: $SESSION.delete(...) + - pattern: $SESSION.head(...) + - pattern: $SESSION.patch(...) + fix-regex: + regex: (.*)\)$ + replacement: \1, timeout=30) + message: >- + Detected a 'requests' call without a timeout set. By default, 'requests' calls + wait until the connection is closed. This means a 'requests' call without a timeout + will hang the program if a response is never received. Consider setting a timeout + for all 'requests'. + languages: [python] + severity: WARNING + metadata: + category: best-practice + references: + - https://docs.python-requests.org/en/latest/user/advanced/?highlight=timeout#timeouts + - https://requests.readthedocs.io/en/latest/user/quickstart/#timeouts + technology: + - requests +- id: python.requests.security.disabled-cert-validation.disabled-cert-validation + message: >- + Certificate verification has been explicitly disabled. This + permits insecure connections to insecure servers. Re-enable + certification validation. + metadata: + cwe: + - 'CWE-295: Improper Certificate Validation' + owasp: + - A03:2017 - Sensitive Data Exposure + - A07:2021 - Identification and Authentication Failures + references: + - https://stackoverflow.com/questions/41740361/is-it-safe-to-disable-ssl-certificate-verification-in-pythonss-requests-lib + category: security + technology: + - requests + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [python] + severity: ERROR + pattern-either: + - pattern: requests.put(..., verify=False, ...) + - pattern: requests.patch(..., verify=False, ...) + - pattern: requests.delete(..., verify=False, ...) + - pattern: requests.head(..., verify=False, ...) + - pattern: requests.options(..., verify=False, ...) + - pattern: requests.request(..., verify=False, ...) + - pattern: requests.get(..., verify=False, ...) + - pattern: requests.post(..., verify=False, ...) + fix-regex: + regex: verify(\s)*=(\s)*False + replacement: verify=True +- id: python.requests.security.no-auth-over-http.no-auth-over-http + fix-regex: + regex: http:\/\/ + replacement: https:// + count: 1 + message: >- + Authentication detected over HTTP. HTTP does not provide any + encryption or protection for these authentication credentials. + This may expose these credentials to unauthorized parties. + Use 'https://' instead. + metadata: + cwe: + - 'CWE-523: Unprotected Transport of Credentials' + owasp: + - A02:2017 - Broken Authentication + - A02:2021 - Cryptographic Failures + source-rule-url: https://pypi.org/project/flake8-flask/ + references: + - https://semgrep.dev/blog/2020/bento-check-no-auth-over-http/ + - https://bento.dev/checks/requests/no-auth-over-http/ + category: security + technology: + - requests + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [python] + severity: ERROR + pattern-either: + - pattern: requests.$W("=~/http:\/\/.*/", ..., auth=$X, ...) + - pattern: | + $URL = "=~/http:\/\/.../" + ... + requests.$W($URL, ..., auth=$X, ...) +- id: python.sh.security.string-concat.string-concat + languages: [python] + severity: ERROR + message: >- + Detected string concatenation or formatting in a call to a command via 'sh'. + This could be a command injection vulnerability if the data is user-controlled. + Instead, use a list and append the argument. + metadata: + cwe: + - "CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')" + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + category: security + technology: + - sh + references: + - https://owasp.org/Top10/A03_2021-Injection + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + pattern-either: + - pattern: sh.$BIN($X + $Y) + - pattern: sh.$BIN($X.format(...)) + - pattern: sh.$BIN(f"...{...}...") +- id: python.sqlalchemy.correctness.bad-operator-in-filter.bad-operator-in-filter + languages: [python] + message: >- + Only comparison operators should be used inside SQLAlchemy filter expressions. Use `==` instead of `is`, + `!=` instead of `is not`, `sqlalchemy.and_` instead of `and`, `sqlalchemy.or_` instead of `or`, + `sqlalchemy.not_` instead of `not`, and `sqlalchemy.in_` instead of `in_`. + metadata: + references: + - https://docs.sqlalchemy.org/en/13/orm/tutorial.html#common-filter-operators + category: correctness + technology: + - sqlalchemy + patterns: + - pattern-inside: | + def $ANY(...): + ... + $MODEL.query + - pattern-inside: | + $TARGET.filter(...) + - pattern-either: + - pattern: not $A + - pattern: $A is $B + - pattern: $A is not $B + - pattern: $A and $B + - pattern: $A or $B + - pattern: $A in $B + - pattern: $A not in $B + severity: WARNING +- id: python.sqlalchemy.correctness.delete-where.delete-where-no-execute + patterns: + - pattern: $X.delete().where(...) + - pattern-not-inside: $X.delete().where(...).execute() + - pattern-not-inside: $C.execute(...) + message: + .delete().where(...) results in a no-op in SQLAlchemy unless the command is executed, use .filter(...).delete() + instead. + languages: [python] + severity: ERROR + metadata: + category: correctness + technology: + - sqlalchemy +- id: python.sqlalchemy.performance.performance-improvements.len-all-count + pattern: len($X.all()) + message: + Using QUERY.count() instead of len(QUERY.all()) sends less data to the client since the SQLAlchemy method is performed + server-side. + languages: [python] + severity: WARNING + metadata: + category: performance + technology: + - sqlalchemy +- id: python.sqlalchemy.performance.performance-improvements.batch-import + pattern: | + for $X in $Y: + db.session.add($Z) + message: Rather than adding one element at a time, consider batch loading to improve performance. + languages: [python] + severity: WARNING + metadata: + category: performance + technology: + - sqlalchemy +- id: python.sqlalchemy.security.audit.avoid-sqlalchemy-text.avoid-sqlalchemy-text + mode: taint + pattern-sinks: + - pattern: | + sqlalchemy.text(...) + pattern-sources: + - patterns: + - pattern: | + $X + $Y + - metavariable-type: + metavariable: $X + type: string + - patterns: + - pattern: | + $X + $Y + - metavariable-type: + metavariable: $Y + type: string + - patterns: + - pattern: | + f"..." + - patterns: + - pattern: | + $X.format(...) + - metavariable-type: + metavariable: $X + type: string + - patterns: + - pattern: | + $X % $Y + - metavariable-type: + metavariable: $X + type: string + message: sqlalchemy.text passes the constructed SQL statement to the database mostly unchanged. This + means that the usual SQL injection protections are not applied and this function is vulnerable to + SQL injection if user input can reach here. Use normal SQLAlchemy operators (such as or_, and_, etc.) + to construct SQL. + metadata: + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + cwe: + - "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')" + category: security + technology: + - sqlalchemy + confidence: MEDIUM + references: + - https://docs.sqlalchemy.org/en/14/core/tutorial.html#using-textual-sql + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: LOW + languages: + - python + severity: ERROR +- id: python.sqlalchemy.security.sqlalchemy-execute-raw-query.sqlalchemy-execute-raw-query + message: >- + Avoiding SQL string concatenation: untrusted input concatenated with raw + SQL query can result in SQL Injection. In order to execute raw query + safely, prepared statement should be used. + SQLAlchemy provides TextualSQL to easily used prepared statement with + named parameters. For complex SQL composition, use SQL Expression + Language or Schema Definition Language. In most cases, SQLAlchemy ORM + will be a better option. + metadata: + cwe: + - "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')" + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + references: + - https://docs.sqlalchemy.org/en/14/core/tutorial.html#using-textual-sql + - https://www.tutorialspoint.com/sqlalchemy/sqlalchemy_quick_guide.htm + - https://docs.sqlalchemy.org/en/14/core/tutorial.html#using-more-specific-text-with-table-expression-literal-column-and-expression-column + category: security + technology: + - sqlalchemy + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH + confidence: LOW + severity: ERROR + languages: + - python + pattern-either: + - pattern: | + $CONNECTION.execute( $SQL + ..., ... ) + - pattern: | + $CONNECTION.execute( $SQL % (...), ...) + - pattern: | + $CONNECTION.execute( $SQL.format(...), ... ) + - pattern: | + $CONNECTION.execute(f"...{...}...", ...) + - patterns: + - pattern-inside: | + $QUERY = $SQL + ... + ... + - pattern: | + $CONNECTION.execute($QUERY, ...) + - patterns: + - pattern-inside: | + $QUERY = $SQL % (...) + ... + - pattern: | + $CONNECTION.execute($QUERY, ...) + - patterns: + - pattern-inside: | + $QUERY = $SQL.format(...) + ... + - pattern: | + $CONNECTION.execute($QUERY, ...) + - patterns: + - pattern-inside: | + $QUERY = f"...{...}..." + ... + - pattern: | + $CONNECTION.execute($QUERY, ...) +- id: python.sqlalchemy.security.sqlalchemy-sql-injection.sqlalchemy-sql-injection + patterns: + - pattern-either: + - pattern: | + def $FUNC(...,$VAR,...): + ... + $SESSION.query(...).$SQLFUNC("...".$FORMATFUNC(...,$VAR,...)) + - pattern: | + def $FUNC(...,$VAR,...): + ... + $SESSION.query.join(...).$SQLFUNC("...".$FORMATFUNC(...,$VAR,...)) + - pattern: | + def $FUNC(...,$VAR,...): + ... + $SESSION.query.$SQLFUNC("...".$FORMATFUNC(...,$VAR,...)) + - pattern: | + def $FUNC(...,$VAR,...): + ... + query.$SQLFUNC("...".$FORMATFUNC(...,$VAR,...)) + - metavariable-regex: + metavariable: $SQLFUNC + regex: (group_by|order_by|distinct|having|filter) + - metavariable-regex: + metavariable: $FORMATFUNC + regex: (?!bindparams) + message: >- + Distinct, Having, Group_by, Order_by, and Filter in SQLAlchemy can cause sql injections + if the developer inputs raw SQL into the before-mentioned clauses. + This pattern captures relevant cases in which the developer inputs raw SQL into the distinct, having, + group_by, order_by or filter clauses and + injects user-input into the raw SQL with any function besides "bindparams". Use bindParams to securely + bind user-input + to SQL statements. + fix-regex: + regex: format + replacement: bindparams + languages: + - python + severity: WARNING + metadata: + cwe: + - "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')" + category: security + technology: + - sqlalchemy + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + references: + - https://owasp.org/Top10/A03_2021-Injection + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: LOW + impact: HIGH + confidence: MEDIUM +- id: python.twilio.security.twiml-injection.twiml-injection + languages: [python] + severity: WARNING + message: >- + Using non-constant TwiML (Twilio Markup Language) argument when creating a + Twilio conversation could allow the injection of additional TwiML commands + metadata: + cwe: + - "CWE-91: XML Injection" + owasp: + - "A03:2021 - Injection" + category: security + technology: + - python + - twilio + - twiml + confidence: MEDIUM + likelihood: HIGH + impact: MEDIUM + subcategory: vuln + references: + - https://codeberg.org/fennix/funjection + mode: taint + pattern-sources: + - pattern: | + f"..." + - pattern: | + "..." % ... + - pattern: | + "...".format(...) + + - patterns: + - pattern: $ARG + - pattern-inside: | + def $F(..., $ARG, ...): + ... + + pattern-sanitizers: + - pattern: xml.sax.saxutils.escape(...) + - pattern: html.escape(...) + + pattern-sinks: + - patterns: + - pattern: | + $CLIENT.calls.create(..., twiml=$SINK, ...) + + - focus-metavariable: $SINK +- id: ruby.aws-lambda.security.activerecord-sqli.activerecord-sqli + languages: + - ruby + message: >- + Detected SQL statement that is tainted by `event` object. This could lead to SQL injection if the + variable is user-controlled + and not properly sanitized. In order to prevent SQL injection, + use parameterized queries or prepared statements instead. + You can use parameterized statements like so: + `Example.find_by_sql ["SELECT title FROM posts WHERE author = ? AND created > ?", author_id, start_date]` + mode: taint + metadata: + references: + - https://guides.rubyonrails.org/active_record_querying.html#finding-by-sql + category: security + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + cwe: + - "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')" + technology: + - aws-lambda + - active-record + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: HIGH + confidence: MEDIUM + pattern-sinks: + - patterns: + - pattern: $QUERY + - pattern-either: + - pattern: ActiveRecord::Base.connection.execute($QUERY,...) + - pattern: $MODEL.find_by_sql($QUERY,...) + - pattern: $MODEL.select_all($QUERY,...) + - pattern-inside: | + require 'active_record' + ... + pattern-sources: + - patterns: + - pattern: event + - pattern-inside: | + def $HANDLER(event, context) + ... + end + severity: WARNING +- id: ruby.aws-lambda.security.mysql2-sqli.mysql2-sqli + languages: + - ruby + message: >- + Detected SQL statement that is tainted by `event` object. This could lead to SQL injection if the + variable is user-controlled + and not properly sanitized. In order to prevent SQL injection, + use parameterized queries or prepared statements instead. + You can use sanitize statements like so: `escaped = client.escape(user_input)` + mode: taint + metadata: + references: + - https://github.com/brianmario/mysql2 + category: security + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + cwe: + - "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')" + technology: + - aws-lambda + - mysql2 + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: HIGH + confidence: MEDIUM + pattern-sinks: + - patterns: + - pattern: $QUERY + - pattern-either: + - pattern: $CLIENT.query($QUERY,...) + - pattern: $CLIENT.prepare($QUERY,...) + - pattern-inside: | + require 'mysql2' + ... + pattern-sanitizers: + - pattern: $CLIENT.escape(...) + pattern-sources: + - patterns: + - pattern: event + - pattern-inside: | + def $HANDLER(event, context) + ... + end + severity: WARNING +- id: ruby.aws-lambda.security.pg-sqli.pg-sqli + languages: + - ruby + message: >- + Detected SQL statement that is tainted by `event` object. This could lead to SQL injection if the + variable is user-controlled + and not properly sanitized. In order to prevent SQL injection, + use parameterized queries or prepared statements instead. + You can use parameterized statements like so: + `conn.exec_params('SELECT $1 AS a, $2 AS b, $3 AS c', [1, 2, nil])` + mode: taint + metadata: + references: + - https://www.rubydoc.info/gems/pg/PG/Connection + category: security + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + cwe: + - "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')" + technology: + - aws-lambda + - postgres + - pg + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: HIGH + confidence: MEDIUM + pattern-sinks: + - patterns: + - pattern: $QUERY + - pattern-either: + - pattern: $CONN.exec($QUERY,...) + - pattern: $CONN.exec_params($QUERY,...) + - pattern: $CONN.exec_prepared($QUERY,...) + - pattern: $CONN.async_exec($QUERY,...) + - pattern: $CONN.async_exec_params($QUERY,...) + - pattern: $CONN.async_exec_prepared($QUERY,...) + - pattern-inside: | + require 'pg' + ... + pattern-sources: + - patterns: + - pattern: event + - pattern-inside: | + def $HANDLER(event, context) + ... + end + severity: WARNING +- id: ruby.aws-lambda.security.sequel-sqli.sequel-sqli + languages: + - ruby + message: >- + Detected SQL statement that is tainted by `event` object. This could lead to SQL injection if the + variable is user-controlled + and not properly sanitized. In order to prevent SQL injection, + use parameterized queries or prepared statements instead. + You can use parameterized statements like so: + `DB['select * from items where name = ?', name]` + mode: taint + metadata: + references: + - https://github.com/jeremyevans/sequel#label-Arbitrary+SQL+queries + category: security + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + cwe: + - "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')" + technology: + - aws-lambda + - sequel + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: HIGH + confidence: MEDIUM + pattern-sinks: + - patterns: + - pattern: $QUERY + - pattern-either: + - pattern: DB[$QUERY,...] + - pattern: DB.run($QUERY,...) + - pattern-inside: | + require 'sequel' + ... + pattern-sources: + - patterns: + - pattern: event + - pattern-inside: | + def $HANDLER(event, context) + ... + end + severity: WARNING +- id: ruby.aws-lambda.security.tainted-deserialization.tainted-deserialization + mode: taint + languages: [ruby] + message: >- + Deserialization of a string tainted by `event` object found. Objects in Ruby can be serialized into + strings, + then later loaded from strings. However, uses of `load` can cause remote code execution. + Loading user input with MARSHAL, YAML or CSV can potentially be dangerous. + If you need to deserialize untrusted data, you should use JSON as it is only capable of returning + 'primitive' types + such as strings, arrays, hashes, numbers and nil. + metadata: + references: + - https://ruby-doc.org/core-3.1.2/doc/security_rdoc.html + - https://groups.google.com/g/rubyonrails-security/c/61bkgvnSGTQ/m/nehwjA8tQ8EJ + - https://github.com/presidentbeef/brakeman/blob/main/lib/brakeman/checks/check_deserialize.rb + category: security + owasp: + - A08:2017 - Insecure Deserialization + - A08:2021 - Software and Data Integrity Failures + cwe: + - 'CWE-502: Deserialization of Untrusted Data' + technology: + - ruby + - aws-lambda + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: HIGH + confidence: MEDIUM + pattern-sinks: + - patterns: + - pattern: $SINK + - pattern-either: + - pattern-inside: | + YAML.load($SINK,...) + - pattern-inside: | + CSV.load($SINK,...) + - pattern-inside: | + Marshal.load($SINK,...) + - pattern-inside: | + Marshal.restore($SINK,...) + pattern-sources: + - patterns: + - pattern: event + - pattern-inside: | + def $HANDLER(event, context) + ... + end + severity: WARNING +- id: ruby.aws-lambda.security.tainted-sql-string.tainted-sql-string + languages: [ruby] + severity: ERROR + message: >- + Detected user input used to manually construct a SQL string. This is usually + bad practice because manual construction could accidentally result in a SQL + injection. An attacker could use a SQL injection to steal or modify contents + of the database. Instead, use a parameterized query which is available + by default in most database engines. Alternatively, consider using an + object-relational mapper (ORM) such as Sequelize which will protect your queries. + metadata: + references: + - https://rorsecurity.info/portfolio/ruby-on-rails-sql-injection-cheat-sheet + category: security + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + cwe: + - "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')" + technology: + - aws-lambda + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: HIGH + confidence: MEDIUM + mode: taint + pattern-sources: + - patterns: + - pattern: event + - pattern-inside: | + def $HANDLER(event, context) + ... + end + pattern-sinks: + - patterns: + - pattern-either: + - patterns: + - pattern: | + "...#{...}..." + - pattern-regex: (?i)(select|delete|insert|create|update|alter|drop)\b|\w+\s*!?[<>=].* + - patterns: + - pattern-either: + - pattern: Kernel::sprintf("$SQLSTR", ...) + - pattern: | + "$SQLSTR" + $EXPR + - pattern: | + "$SQLSTR" % $EXPR + - metavariable-regex: + metavariable: $SQLSTR + regex: (?i)(select|delete|insert|create|update|alter|drop)\b|\w+\s*!?[<>=].* + - pattern-not-inside: | + puts(...) +- id: ruby.jwt.security.audit.jwt-decode-without-verify.ruby-jwt-decode-without-verify + message: >- + Detected the decoding of a JWT token without a verify step. + JWT tokens must be verified before use, otherwise the token's + integrity is unknown. This means a malicious actor could forge + a JWT token with any claims. + metadata: + cwe: + - 'CWE-345: Insufficient Verification of Data Authenticity' + owasp: + - A08:2021 - Software and Data Integrity Failures + source-rule-url: https://semgrep.dev/blog/2020/hardcoded-secrets-unverified-tokens-and-other-common-jwt-mistakes/ + category: security + technology: + - jwt + references: + - https://owasp.org/Top10/A08_2021-Software_and_Data_Integrity_Failures + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [ruby] + severity: WARNING + patterns: + - pattern-inside: | + require 'jwt' + ... + - pattern: |- + JWT.decode($PAYLOAD,$SECRET,false,...) +- id: ruby.jwt.security.audit.jwt-exposed-data.ruby-jwt-exposed-data + message: >- + The object is passed strictly to jsonwebtoken.sign(...) + Make sure that sensitive information is not exposed through JWT token payload. + severity: WARNING + metadata: + owasp: + - A02:2017 - Broken Authentication + - A04:2021 - Insecure Design + cwe: + - 'CWE-522: Insufficiently Protected Credentials' + source-rule-url: https://semgrep.dev/blog/2020/hardcoded-secrets-unverified-tokens-and-other-common-jwt-mistakes/ + category: security + technology: + - jwt + references: + - https://owasp.org/Top10/A04_2021-Insecure_Design + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [ruby] + patterns: + - pattern-inside: | + require 'jwt' + ... + - pattern-inside: | + def $FUNC(...,$INPUT,...) + ... + end + - pattern: | + JWT.encode($INPUT,...) +- id: ruby.jwt.security.jwt-exposed-credentials.ruby-jwt-exposed-credentials + languages: + - ruby + metadata: + cwe: + - 'CWE-522: Insufficiently Protected Credentials' + owasp: + - A02:2017 - Broken Authentication + - A04:2021 - Insecure Design + source-rule-url: https://semgrep.dev/blog/2020/hardcoded-secrets-unverified-tokens-and-other-common-jwt-mistakes/ + references: + - https://cwe.mitre.org/data/definitions/522.html + category: security + technology: + - jwt + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + message: >- + Password is exposed through JWT token payload. This is not encrypted and + the password could be compromised. Do not store passwords in JWT tokens. + patterns: + - pattern-inside: | + require 'jwt' + ... + - pattern: | + $PAYLOAD = {...,password:...,...} + ... + JWT.encode($PAYLOAD,...) + severity: ERROR +- id: ruby.jwt.security.jwt-hardcode.ruby-jwt-hardcoded-secret + message: >- + Hardcoded JWT secret or private key is used. + This is a Insufficiently Protected Credentials weakness: https://cwe.mitre.org/data/definitions/522.html + Consider using an appropriate security mechanism to protect the credentials (e.g. keeping secrets + in environment variables) + metadata: + cwe: + - 'CWE-522: Insufficiently Protected Credentials' + owasp: + - A02:2017 - Broken Authentication + - A04:2021 - Insecure Design + source-rule-url: https://semgrep.dev/blog/2020/hardcoded-secrets-unverified-tokens-and-other-common-jwt-mistakes/ + category: security + technology: + - jwt + references: + - https://owasp.org/Top10/A04_2021-Insecure_Design + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + patterns: + - pattern-inside: | + require 'jwt' + ... + - pattern-either: + - pattern: | + JWT.encode($PAYLOAD,"...",...) + - pattern: | + JWT.decode($PAYLOAD,"...",...) + - pattern: | + JWT.encode($PAYLOAD,nil,...) + - pattern: | + JWT.decode($PAYLOAD,nil,...) + - pattern: | + $SECRET = "..." + ... + JWT.encode($PAYLOAD,$SECRET,...) + - pattern: | + $SECRET = "..." + ... + JWT.decode($PAYLOAD,$SECRET,...) + - pattern-not: | + JWT.encode($PAYLOAD, nil, ... , jwks: ..., ...) + - pattern-not: | + JWT.decode($PAYLOAD, nil, ..., jwks: ..., ...) + languages: [ruby] + severity: ERROR +- id: ruby.jwt.security.jwt-none-alg.ruby-jwt-none-alg + message: >- + Detected use of the 'none' algorithm in a JWT token. + The 'none' algorithm assumes the integrity of the token has already + been verified. This would allow a malicious actor to forge a JWT token + that will automatically be verified. Do not explicitly use the 'none' + algorithm. Instead, use an algorithm such as 'HS256'. + metadata: + cwe: + - 'CWE-327: Use of a Broken or Risky Cryptographic Algorithm' + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + source-rule-url: https://semgrep.dev/blog/2020/hardcoded-secrets-unverified-tokens-and-other-common-jwt-mistakes/ + category: security + technology: + - jwt + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [ruby] + severity: ERROR + patterns: + - pattern-inside: | + require 'jwt' + ... + - pattern: | + JWT.encode($PAYLOAD, $SECRET, 'none', ...) +- id: ruby.lang.security.bad-deserialization-env.bad-deserialization-env + mode: taint + pattern-sources: + - pattern-either: + - pattern: request.env + pattern-sinks: + - pattern-either: + - pattern: | + CSV.load(...) + - pattern: | + Marshal.load(...) + - pattern: | + Marshal.restore(...) + - pattern: | + Oj.object_load(...) + - pattern: | + Oj.load($X) + message: >- + Checks for unsafe deserialization. Objects in Ruby can be serialized into strings, + then later loaded from strings. However, uses of load and object_load can cause remote code execution. + Loading user input with MARSHAL or CSV can potentially be dangerous. Use JSON in a secure fashion + instead. + metadata: + references: + - https://groups.google.com/g/rubyonrails-security/c/61bkgvnSGTQ/m/nehwjA8tQ8EJ + - https://github.com/presidentbeef/brakeman/blob/main/lib/brakeman/checks/check_deserialize.rb + category: security + cwe: + - 'CWE-502: Deserialization of Untrusted Data' + owasp: + - A08:2017 - Insecure Deserialization + - A08:2021 - Software and Data Integrity Failures + technology: + - ruby + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: LOW + impact: HIGH + confidence: LOW + languages: + - ruby + severity: ERROR +- id: ruby.lang.security.bad-deserialization-yaml.bad-deserialization-yaml + patterns: + - pattern: | + YAML.load($...ARGS) + - pattern-not: | + YAML.load(..., safe: true, ...) + - pattern-not: | + YAML.load("...", ...) + - pattern-not-inside: | + YAML.load(..., File.read(...), ...) + - pattern-not-inside: | + $FILE = File.read(...) + ... + YAML.load(..., $FILE, ...) + - pattern-not-inside: | + $FILENAME = ... + ... + $FILE = File.read($FILENAME, ...) + ... + YAML.load(..., $FILE, ...) + - pattern-not-inside: | + YAML.load(..., $X.$Y(File.read(...)), ...) + - pattern-not-inside: | + YAML.load(..., $X.$Y(File.read(...)).$Z, ...) + - pattern-not-inside: | + $T = $MOD.$MET(File.read(...)) + ... + YAML.load(..., $T, ...) + - pattern-not-inside: | + $T = $MOD.$MET(File.read(...)) + ... + YAML.load(..., $T.$R, ...) + fix: Psych.safe_load($...ARGS) + message: >- + Unsafe deserialization from YAML. Objects in Ruby can be serialized into strings, + then later loaded from strings. However, uses of load and object_load can cause remote code execution. + Loading user input with YAML can potentially be dangerous. Use JSON in a secure fashion instead. + However, loading YAML from a static file is not dangerous and should not be flagged. + metadata: + cwe: + - 'CWE-502: Deserialization of Untrusted Data' + references: + - https://groups.google.com/g/rubyonrails-security/c/61bkgvnSGTQ/m/nehwjA8tQ8EJ + - https://github.com/presidentbeef/brakeman/blob/main/lib/brakeman/checks/check_deserialize.rb + category: security + technology: + - ruby + - yaml + owasp: + - A08:2017 - Insecure Deserialization + - A08:2021 - Software and Data Integrity Failures + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH + confidence: LOW + languages: + - ruby + severity: ERROR +- id: ruby.lang.security.bad-deserialization.bad-deserialization + mode: taint + pattern-sources: + - pattern-either: + - pattern: params + - pattern: cookies + pattern-sinks: + - pattern-either: + - pattern: | + CSV.load(...) + - pattern: | + Marshal.load(...) + - pattern: | + Marshal.restore(...) + - pattern: | + Oj.object_load(...) + - pattern: | + Oj.load($X) + message: >- + Checks for unsafe deserialization. Objects in Ruby can be serialized into strings, + then later loaded from strings. However, uses of load and object_load can cause remote code execution. + Loading user input with MARSHAL or CSV can potentially be dangerous. Use JSON in a secure fashion + instead. + metadata: + references: + - https://groups.google.com/g/rubyonrails-security/c/61bkgvnSGTQ/m/nehwjA8tQ8EJ + - https://github.com/presidentbeef/brakeman/blob/main/lib/brakeman/checks/check_deserialize.rb + category: security + cwe: + - 'CWE-502: Deserialization of Untrusted Data' + owasp: + - A08:2017 - Insecure Deserialization + - A08:2021 - Software and Data Integrity Failures + technology: + - ruby + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: HIGH + confidence: MEDIUM + languages: + - ruby + severity: ERROR +- id: ruby.lang.security.cookie-serialization.cookie-serialization + message: >- + Checks if code allows cookies to be deserialized using Marshal. If the attacker + can craft a valid cookie, this could lead to + remote code execution. The hybrid check is just to warn users to migrate to :json + for best practice. + metadata: + cwe: + - "CWE-94: Improper Control of Generation of Code ('Code Injection')" + references: + - https://github.com/presidentbeef/brakeman/blob/main/lib/brakeman/checks/check_cookie_serialization.rb + - https://robertheaton.com/2013/07/22/how-to-hack-a-rails-app-using-its-secret-token/ + category: security + technology: + - ruby + owasp: + - A03:2021 - Injection + cwe2022-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH + confidence: LOW + languages: + - ruby + severity: ERROR + pattern-either: + - pattern: | + Rails.application.config.action_dispatch.cookies_serializer = :marshal + - pattern: | + Rails.application.config.action_dispatch.cookies_serializer = :hybrid +- id: ruby.lang.security.create-with.create-with + patterns: + - pattern-not: | + $FUNC.create_with($PARAMSB.permit(...)) + - pattern: | + $FUNC.create_with($PARAMSA) + message: >- + Checks for strong parameter bypass through usage of create_with. Create_with bypasses + strong parameter protection, which + could allow attackers to set arbitrary attributes on models. To fix this vulnerability, + either remove all create_with calls + or use the permit function to specify tags that are allowed to be set. + metadata: + cwe: + - 'CWE-915: Improperly Controlled Modification of Dynamically-Determined Object Attributes' + references: + - https://github.com/presidentbeef/brakeman/blob/main/lib/brakeman/checks/check_create_with.rb + - https://groups.google.com/g/rubyonrails-security/c/M4chq5Sb540/m/CC1Fh0Y_NWwJ + category: security + technology: + - ruby + owasp: + - A08:2021 - Software and Data Integrity Failures + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + languages: + - ruby + severity: ERROR +- id: ruby.lang.security.dangerous-exec.dangerous-exec + mode: taint + pattern-sources: + - patterns: + - pattern: | + def $F(...,$ARG,...) + ... + end + - focus-metavariable: $ARG + - pattern: params + - pattern: cookies + pattern-sinks: + - patterns: + - pattern: | + $EXEC(...) + - pattern-not: | + $EXEC("...","...","...",...) + - pattern-not: | + $EXEC(["...","...","...",...],...) + - pattern-not: | + $EXEC({...},"...","...","...",...) + - pattern-not: | + $EXEC({...},["...","...","...",...],...) + - metavariable-regex: + metavariable: $EXEC + regex: ^(system|exec|spawn|Process.exec|Process.spawn|Open3.capture2|Open3.capture2e|Open3.capture3|Open3.popen2|Open3.popen2e|Open3.popen3|IO.popen|Gem::Util.popen|PTY.spawn)$ + message: >- + Detected non-static command inside $EXEC. Audit the input to '$EXEC'. + If unverified user data can reach this call site, this is a code injection + vulnerability. A malicious actor can inject a malicious script to execute + arbitrary code. + metadata: + source-rule-url: https://github.com/presidentbeef/brakeman/blob/main/lib/brakeman/checks/check_execute.rb + cwe: + - "CWE-94: Improper Control of Generation of Code ('Code Injection')" + owasp: + - A03:2021 - Injection + category: security + technology: + - ruby + - rails + references: + - https://guides.rubyonrails.org/security.html#command-line-injection + cwe2022-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: HIGH + confidence: MEDIUM + severity: WARNING + languages: [ruby] +- id: ruby.lang.security.dangerous-open.dangerous-open + patterns: + - pattern: | + open($CMD,...) + - pattern-not: | + open("...",...) + - metavariable-regex: + metavariable: $CMD + regex: '|' + message: >- + Detected non-static command inside 'open'. Audit the input to 'open'. + If unverified user data can reach this call site, this is a code injection + vulnerability. A malicious actor can inject a malicious script to execute + arbitrary code. + metadata: + cwe: + - "CWE-94: Improper Control of Generation of Code ('Code Injection')" + owasp: + - A03:2021 - Injection + category: security + technology: + - ruby + references: + - https://owasp.org/Top10/A03_2021-Injection + cwe2022-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH + confidence: LOW + severity: WARNING + languages: [ruby] +- id: ruby.lang.security.dangerous-open3-pipeline.dangerous-open3-pipeline + patterns: + - pattern: | + Open3.$PIPE(...) + - pattern-not: | + Open3.$PIPE(...,"...",...) + - metavariable-regex: + metavariable: $PIPE + regex: ^(pipeline|pipeline_r|pipeline_rw|pipeline_start|pipeline_w)$ + message: >- + Detected non-static command inside $PIPE. Audit the input to '$PIPE'. + If unverified user data can reach this call site, this is a code injection + vulnerability. A malicious actor can inject a malicious script to execute + arbitrary code. + metadata: + cwe: + - "CWE-94: Improper Control of Generation of Code ('Code Injection')" + owasp: + - A03:2021 - Injection + category: security + technology: + - ruby + references: + - https://owasp.org/Top10/A03_2021-Injection + cwe2022-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH + confidence: LOW + severity: WARNING + languages: [ruby] +- id: ruby.lang.security.dangerous-subshell.dangerous-subshell + patterns: + - pattern: | + `...#{$VAL}...` + - pattern-not: | + `...#{"..."}...` + - pattern-not-inside: | + $VAL = "..." + ... + message: >- + Detected non-static command inside `...`. + If unverified user data can reach this call site, this is a code injection + vulnerability. A malicious actor can inject a malicious script to execute + arbitrary code. + metadata: + cwe: + - "CWE-94: Improper Control of Generation of Code ('Code Injection')" + owasp: + - A03:2021 - Injection + category: security + technology: + - ruby + references: + - https://owasp.org/Top10/A03_2021-Injection + cwe2022-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH + confidence: LOW + severity: WARNING + languages: [ruby] +- id: ruby.lang.security.dangerous-syscall.dangerous-syscall + pattern: | + syscall + message: >- + 'syscall' is essentially unsafe and unportable. The DL (https://apidock.com/ruby/Fiddle) + library is preferred for safer and a bit more portable programming. + metadata: + cwe: + - "CWE-94: Improper Control of Generation of Code ('Code Injection')" + owasp: + - A03:2021 - Injection + category: security + technology: + - ruby + references: + - https://owasp.org/Top10/A03_2021-Injection + cwe2022-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH + confidence: LOW + severity: WARNING + languages: [ruby] +- id: ruby.lang.security.divide-by-zero.divide-by-zero + message: >- + Detected a possible ZeroDivisionError. + metadata: + cwe: + - 'CWE-369: Divide By Zero' + references: + - https://github.com/presidentbeef/brakeman/blob/main/lib/brakeman/checks/check_divide_by_zero.rb + category: security + technology: + - ruby + confidence: MEDIUM + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + languages: + - ruby + severity: WARNING + mode: taint + pattern-sources: + - patterns: + - pattern: $VAR + - metavariable-regex: + metavariable: $VAR + regex: ^\d*(?!\.)$ + pattern-sinks: + - patterns: + - pattern-inside: $NUMER / 0 + - pattern: $NUMER +- id: ruby.lang.security.file-disclosure.file-disclosure + message: >- + Special requests can determine whether a file exists on a filesystem that's outside + the Rails app's + root directory. To fix this, set config.serve_static_assets = false. + metadata: + cwe: + - "CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')" + references: + - https://github.com/presidentbeef/brakeman/blob/main/lib/brakeman/checks/check_file_disclosure.rb + - https://groups.google.com/g/rubyonrails-security/c/23fiuwb1NBA/m/MQVM1-5GkPMJ + category: security + technology: + - ruby + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + languages: + - ruby + severity: ERROR + pattern: config.serve_static_assets = true + fix-regex: + regex: =(\s)*true + replacement: = false +- id: ruby.lang.security.filter-skipping.filter-skipping + patterns: + - pattern-not: | + $CALL "=~/.*(/:action.*).*/", $ACTION + - pattern: | + $CALL "=~/.*(/:action.*).*/" + message: >- + Checks for use of action in Ruby routes. This can cause Rails to render an arbitrary + view if an + attacker creates an URL accurately. Affects 3.0 applications. Can avoid the vulnerability + by providing + additional constraints. + metadata: + cwe: + - 'CWE-1021: Improper Restriction of Rendered UI Layers or Frames' + references: + - https://github.com/presidentbeef/brakeman/blob/main/lib/brakeman/checks/check_filter_skipping.rb + - https://groups.google.com/g/rubyonrails-security/c/NCCsca7TEtY + category: security + technology: + - ruby + owasp: + - A04:2021 - Insecure Design + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + languages: + - ruby + severity: ERROR +- id: ruby.lang.security.force-ssl-false.force-ssl-false + message: >- + Checks for configuration setting of force_ssl to false. Force_ssl forces usage + of HTTPS, which + could lead to network interception of unencrypted application traffic. To fix, + set config.force_ssl = true. + metadata: + cwe: + - 'CWE-311: Missing Encryption of Sensitive Data' + references: + - https://github.com/presidentbeef/brakeman/blob/main/lib/brakeman/checks/check_force_ssl.rb + category: security + technology: + - ruby + owasp: + - A03:2017 - Sensitive Data Exposure + - A04:2021 - Insecure Design + subcategory: + - vuln + likelihood: LOW + impact: MEDIUM + confidence: HIGH + languages: + - ruby + severity: WARNING + pattern: config.force_ssl = false + fix-regex: + regex: =\s*false + replacement: = true +- id: ruby.lang.security.hardcoded-http-auth-in-controller.hardcoded-http-auth-in-controller + patterns: + - pattern-inside: | + class $CONTROLLER < ApplicationController + ... + http_basic_authenticate_with ..., :password => "$SECRET", ... + end + - focus-metavariable: $SECRET + message: >- + Detected hardcoded password used in basic authentication in a controller + class. Including this password in version control could expose this + credential. Consider refactoring to use environment variables or + configuration files. + severity: WARNING + metadata: + cwe: + - 'CWE-798: Use of Hard-coded Credentials' + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + source-rule-url: https://github.com/presidentbeef/brakeman/blob/main/docs/warning_types/basic_auth/index.markdown + category: security + technology: + - ruby + - secrets + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: MEDIUM + impact: MEDIUM + confidence: HIGH + languages: + - ruby +- id: ruby.lang.security.hardcoded-secret-rsa-passphrase.hardcoded-secret-rsa-passphrase + message: >- + Found the use of an hardcoded passphrase for RSA. The passphrase can be easily discovered, and therefore + should not be stored in source-code. It is recommended to remove the passphrase from source-code, + and use system environment variables or a restricted configuration file. + languages: + - ruby + severity: WARNING + metadata: + technology: + - ruby + - secrets + category: security + references: + - https://cwe.mitre.org/data/definitions/522.html + cwe: + - 'CWE-798: Use of Hard-coded Credentials' + owasp: + - A07:2021 - Identification and Authentication Failures + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: HIGH + patterns: + - pattern-either: + - pattern: OpenSSL::PKey::RSA.new(..., '...') + - pattern: OpenSSL::PKey::RSA.new(...).to_pem(..., '...') + - pattern: OpenSSL::PKey::RSA.new(...).export(..., '...') + - patterns: + - pattern-inside: | + $OPENSSL = OpenSSL::PKey::RSA.new(...) + ... + - pattern-either: + - pattern: | + $OPENSSL.export(...,'...') + - pattern: | + $OPENSSL.to_pem(...,'...') + - patterns: + - pattern-either: + - patterns: + - pattern-inside: | + $ASSIGN = '...' + ... + - pattern: OpenSSL::PKey::RSA.new(..., $ASSIGN) + - patterns: + - pattern-inside: | + def $METHOD1(...) + ... + $ASSIGN = '...' + ... + end + ... + def $METHOD2(...) + ... + end + - pattern: OpenSSL::PKey::RSA.new(..., $ASSIGN) + - patterns: + - pattern-inside: | + $ASSIGN = '...' + ... + def $METHOD(...) + $OPENSSL = OpenSSL::PKey::RSA.new(...) + ... + end + ... + - pattern-either: + - pattern: $OPENSSL.export(...,$ASSIGN) + - pattern: $OPENSSL.to_pem(...,$ASSIGN) + - patterns: + - pattern-inside: | + def $METHOD1(...) + ... + $OPENSSL = OpenSSL::PKey::RSA.new(...) + ... + $ASSIGN = '...' + ... + end + ... + - pattern-either: + - pattern: $OPENSSL.export(...,$ASSIGN) + - pattern: $OPENSSL.to_pem(...,$ASSIGN) + - patterns: + - pattern-inside: | + def $METHOD1(...) + ... + $ASSIGN = '...' + ... + end + ... + def $METHOD2(...) + ... + $OPENSSL = OpenSSL::PKey::RSA.new(...) + ... + end + ... + - pattern-either: + - pattern: $OPENSSL.export(...,$ASSIGN) + - pattern: $OPENSSL.to_pem(...,$ASSIGN) +- id: ruby.lang.security.insufficient-rsa-key-size.insufficient-rsa-key-size + message: >- + The RSA key size $SIZE is insufficent by NIST standards. It is recommended to use a key length of + 2048 or higher. + languages: [ruby] + severity: WARNING + metadata: + technology: + - ruby + category: security + references: + - https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-57Pt3r1.pdf + cwe: + - 'CWE-326: Inadequate Encryption Strength' + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + subcategory: + - vuln + likelihood: HIGH + impact: MEDIUM + confidence: HIGH + patterns: + - pattern-either: + - pattern: OpenSSL::PKey::RSA.generate($SIZE,...) + - pattern: OpenSSL::PKey::RSA.new($SIZE, ...) + - patterns: + - pattern-either: + - patterns: + - pattern-inside: | + $ASSIGN = $SIZE + ... + - pattern-either: + - pattern: OpenSSL::PKey::RSA.new($ASSIGN, ...) + - pattern: OpenSSL::PKey::RSA.generate($ASSIGN, ...) + - patterns: + - pattern-inside: | + def $METHOD1(...) + ... + $ASSIGN = $SIZE + ... + end + ... + - pattern-either: + - pattern: OpenSSL::PKey::RSA.new($ASSIGN, ...) + - pattern: OpenSSL::PKey::RSA.generate($ASSIGN, ...) + - metavariable-comparison: + metavariable: $SIZE + comparison: $SIZE < 2048 +- id: ruby.lang.security.json-entity-escape.json-entity-escape + pattern-either: + - pattern: | + ActiveSupport.escape_html_entities_in_json = false + - pattern: | + config.active_support.escape_html_entities_in_json = false + message: >- + Checks if HTML escaping is globally disabled for JSON output. This could lead + to XSS. + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + source-rule-url: https://github.com/presidentbeef/brakeman/blob/main/lib/brakeman/checks/check_json_entity_escape.rb + category: security + technology: + - ruby + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + references: + - https://owasp.org/Top10/A03_2021-Injection + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + languages: + - ruby + severity: WARNING +- id: ruby.lang.security.mass-assignment-protection-disabled.mass-assignment-protection-disabled + pattern: $MODEL.new(params[...], ..., :without_protection => true, ...) + message: >- + Mass assignment protection disabled for '$MODEL'. This could + permit assignment to sensitive model fields without intention. Instead, + use 'attr_accessible' for the model or disable mass assigment using + 'config.active_record.whitelist_attributes = true'. + ':without_protection => true' must be removed for this to take effect. + metadata: + cwe: + - 'CWE-915: Improperly Controlled Modification of Dynamically-Determined Object Attributes' + owasp: + - A08:2021 - Software and Data Integrity Failures + source-rule-url: https://github.com/presidentbeef/brakeman/blob/main/docs/warning_types/mass_assignment/index.markdown + category: security + technology: + - ruby + references: + - https://owasp.org/Top10/A08_2021-Software_and_Data_Integrity_Failures + subcategory: + - audit + likelihood: LOW + impact: HIGH + confidence: LOW + severity: WARNING + languages: + - ruby +- id: ruby.lang.security.md5-used-as-password.md5-used-as-password + languages: [ruby] + severity: WARNING + message: >- + It looks like MD5 is used as a password hash. MD5 is not considered a + secure password hash because it can be cracked by an attacker in a short + amount of time. Instead, use a suitable password hashing function such as + bcrypt. You can use the `bcrypt` gem. + metadata: + category: security + technology: + - md5 + references: + - https://tools.ietf.org/id/draft-lvelvindron-tls-md5-sha1-deprecate-01.html + - https://security.stackexchange.com/questions/211/how-to-securely-hash-passwords + - https://github.com/returntocorp/semgrep-rules/issues/1609 + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + cwe: + - 'CWE-327: Use of a Broken or Risky Cryptographic Algorithm' + subcategory: + - vuln + likelihood: HIGH + impact: MEDIUM + confidence: MEDIUM + mode: taint + pattern-sources: + - pattern: Digest::MD5 + pattern-sinks: + - patterns: + - pattern: $FUNCTION(...); + - metavariable-regex: + metavariable: $FUNCTION + regex: (?i)(.*password.*) +- id: ruby.lang.security.missing-csrf-protection.missing-csrf-protection + patterns: + - pattern: | + class $CONTROLLER < ActionController::Base + ... + end + - pattern-not: | + class $CONTROLLER < ActionController::Base + ... + protect_from_forgery :with => :exception + end + - pattern-not: | + class $CONTROLLER < ActionController::Base + ... + protect_from_forgery prepend: true, with: :exception + end + message: >- + Detected controller which does not enable cross-site request forgery + protections using 'protect_from_forgery'. Add + 'protect_from_forgery :with => :exception' to your controller class. + severity: ERROR + metadata: + cwe: + - 'CWE-352: Cross-Site Request Forgery (CSRF)' + owasp: + - A01:2021 - Broken Access Control + source-rule-url: https://github.com/presidentbeef/brakeman/blob/main/docs/warning_types/cross-site_request_forgery/index.markdown + category: security + technology: + - ruby + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + languages: + - ruby +- id: ruby.lang.security.model-attr-accessible.model-attr-accessible + message: >- + Checks for dangerous permitted attributes that can lead to mass assignment vulnerabilities. + Query parameters allowed using permit + and attr_accessible are checked for allowance of dangerous attributes admin, banned, + role, and account_id. Also checks for usages of + params.permit!, which allows everything. Fix: don't allow admin, banned, role, + and account_id using permit or attr_accessible. + metadata: + cwe: + - 'CWE-915: Improperly Controlled Modification of Dynamically-Determined Object Attributes' + references: + - https://github.com/presidentbeef/brakeman/blob/main/lib/brakeman/checks/check_model_attr_accessible.rb + category: security + technology: + - ruby + owasp: + - A08:2021 - Software and Data Integrity Failures + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + languages: + - ruby + severity: ERROR + pattern-either: + - pattern: | + ....permit(..., :admin, ...) + - pattern: | + ....permit(..., :role, ...) + - pattern: | + ....permit(..., :banned, ...) + - pattern: | + ....permit(..., :account_id, ...) + - pattern: | + attr_accessible ..., :admin, ... + - pattern: | + attr_accessible ..., :role, ... + - pattern: | + attr_accessible ..., :banned, ... + - pattern: | + attr_accessible ..., :account_id, ... + - pattern: | + params.permit! +- id: ruby.lang.security.model-attributes-attr-accessible.model-attributes-attr-accessible + patterns: + - pattern-not: | + class $CLASS < $TYPE + ... + attr_accessible :$XXX + ... + end + ... + $CLASS.$FUNC(...) + - pattern: | + class $CLASS < $TYPE + ... + end + ... + $CLASS.$FUNC(...) + - metavariable-pattern: + metavariable: $TYPE + patterns: + - pattern-not-regex: (?i)(Error|Exception) + - focus-metavariable: $CLASS + message: >- + Checks for models that do not use attr_accessible. This means there is no limiting + of which variables can be manipulated + through mass assignment. For newer Rails applications, parameters should be allowlisted + using strong parameters. + For older Rails versions, they should be allowlisted using strong_attributes. + metadata: + references: + - https://github.com/presidentbeef/brakeman/blob/main/lib/brakeman/checks/check_model_attributes.rb + category: security + owasp: + - A08:2021 - Software and Data Integrity Failures + cwe: + - 'CWE-915: Improperly Controlled Modification of Dynamically-Determined Object Attributes' + technology: + - rails + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + languages: + - ruby + severity: ERROR +- id: ruby.lang.security.no-eval.ruby-eval + message: >- + Use of eval with user-controllable input detected. This can lead + to attackers running arbitrary code. Ensure external data does not + reach here, otherwise this is a security vulnerability. Consider + other ways to do this without eval. + severity: WARNING + metadata: + likelihood: HIGH + impact: MEDIUM + confidence: MEDIUM + category: security + cwe2022-top25: true + cwe2021-top25: true + cwe: + - "CWE-94: Improper Control of Generation of Code ('Code Injection')" + owasp: + - A03:2021 - Injection + references: + - https://owasp.org/Top10/A03_2021-Injection + source-rule-url: https://github.com/presidentbeef/brakeman/blob/main/lib/brakeman/checks/check_evaluation.rb + subcategory: + - vuln + technology: + - ruby + - rails + languages: + - ruby + mode: taint + pattern-sources: + - pattern-either: + - pattern: params + - pattern: cookies + - patterns: + - pattern: | + RubyVM::InstructionSequence.compile(...) + - pattern-not: | + RubyVM::InstructionSequence.compile("...") + pattern-sinks: + - patterns: + - pattern-either: + - pattern: $X.eval + - pattern: $X.class_eval + - pattern: $X.instance_eval + - pattern: $X.module_eval + - pattern: $X.eval(...) + - pattern: $X.class_eval(...) + - pattern: $X.instance_eval(...) + - pattern: $X.module_eval(...) + - pattern: eval(...) + - pattern: class_eval(...) + - pattern: module_eval(...) + - pattern: instance_eval(...) + - pattern-not: $M("...",...) +- id: ruby.lang.security.no-send.bad-send + message: >- + Checks for unsafe use of Object#send, try, __send__, and public_send. These only + account for unsafe + use of a method, not target. This can lead to arbitrary calling of exit, along + with arbitrary code execution. + Please be sure to sanitize input in order to avoid this. + metadata: + cwe: + - "CWE-94: Improper Control of Generation of Code ('Code Injection')" + references: + - https://github.com/presidentbeef/brakeman/blob/main/lib/brakeman/checks/check_send.rb + - https://the.igreque.info/posts/2016/01-object-send-considered-harmful-en.html + category: security + technology: + - ruby + owasp: + - A03:2021 - Injection + cwe2022-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + languages: + - ruby + severity: ERROR + pattern-either: + - pattern: | + $PARAM = params[...] + ... + $RES = $MOD.send($PARAM.$FUNC) + - pattern: | + $PARAM = params[...] + ... + $RES = $MOD.try($PARAM.$FUNC) + - pattern: | + $PARAM = params[...] + ... + $RES = $MOD.__send__($PARAM.$FUNC) + - pattern: | + $PARAM = params[...] + ... + $RES = $MOD.public_send($PARAM.$FUNC) +- id: ruby.lang.security.ssl-mode-no-verify.ssl-mode-no-verify + pattern: OpenSSL::SSL::VERIFY_NONE + message: >- + Detected SSL that will accept an unverified connection. + This makes the connections susceptible to man-in-the-middle attacks. + Use 'OpenSSL::SSL::VERIFY_PEER' instead. + fix-regex: + regex: VERIFY_NONE + replacement: VERIFY_PEER + severity: WARNING + languages: + - ruby + metadata: + cwe: + - 'CWE-295: Improper Certificate Validation' + category: security + technology: + - ruby + owasp: + - A03:2017 - Sensitive Data Exposure + - A07:2021 - Identification and Authentication Failures + references: + - https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures + subcategory: + - vuln + likelihood: HIGH + impact: MEDIUM + confidence: MEDIUM +- id: ruby.lang.security.unprotected-mass-assign.mass-assignment-vuln + patterns: + - pattern-either: + - pattern: | + $MOD.new(params[$CODE]) + - pattern: | + $MOD.new(..., params[$CODE], :without_protection => true, ...) + - pattern-not-inside: | + attr_accessible $VAR + ... + $MOD.new(params[$CODE]) + message: >- + Checks for calls to without_protection during mass assignment (which allows record + creation from hash values). + This can lead to users bypassing permissions protections. For Rails 4 and higher, + mass protection is on by default. + Fix: Don't use :without_protection => true. Instead, configure attr_accessible + to control attribute access. + metadata: + owasp: + - A08:2021 - Software and Data Integrity Failures + cwe: + - 'CWE-915: Improperly Controlled Modification of Dynamically-Determined Object Attributes' + references: + - https://github.com/presidentbeef/brakeman/blob/main/lib/brakeman/checks/check_without_protection.rb + - https://www.acunetix.com/vulnerabilities/web/rails-mass-assignment/ + category: security + technology: + - ruby + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + languages: + - ruby + severity: WARNING +- id: ruby.lang.security.weak-hashes-md5.weak-hashes-md5 + message: >- + Should not use md5 to generate hashes. md5 is proven to be vulnerable through + the use of brute-force attacks. + Could also result in collisions, leading to potential collision attacks. Use SHA256 + or other hashing functions instead. + metadata: + cwe: + - 'CWE-328: Use of Weak Hash' + references: + - https://www.ibm.com/support/pages/security-bulletin-vulnerability-md5-signature-and-hash-algorithm-affects-sterling-integrator-and-sterling-file-gateway-cve-2015-7575 + category: security + technology: + - ruby + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + subcategory: + - vuln + likelihood: LOW + impact: HIGH + confidence: MEDIUM + languages: + - ruby + severity: WARNING + pattern-either: + - pattern: Digest::MD5.base64digest $X + - pattern: Digest::MD5.hexdigest $X + - pattern: Digest::MD5.digest $X + - pattern: Digest::MD5.new + - pattern: OpenSSL::Digest::MD5.base64digest $X + - pattern: OpenSSL::Digest::MD5.hexdigest $X + - pattern: OpenSSL::Digest::MD5.digest $X + - pattern: OpenSSL::Digest::MD5.new +- id: ruby.lang.security.weak-hashes-sha1.weak-hashes-sha1 + message: >- + Should not use SHA1 to generate hashes. There is a proven SHA1 hash collision + by Google, which could lead to vulnerabilities. + Use SHA256, SHA3 or other hashing functions instead. + metadata: + cwe: + - 'CWE-328: Use of Weak Hash' + references: + - https://security.googleblog.com/2017/02/announcing-first-sha1-collision.html + - https://shattered.io/ + category: security + technology: + - ruby + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + subcategory: + - vuln + likelihood: LOW + impact: MEDIUM + confidence: MEDIUM + languages: + - ruby + severity: WARNING + pattern-either: + - pattern: Digest::SHA1.$FUNC + - pattern: OpenSSL::Digest::SHA1.$FUNC + - pattern: OpenSSL::HMAC.$FUNC("sha1",...) +- id: ruby.rails.correctness.rails-no-render-after-save.rails-no-render-after-save + mode: taint + pattern-sources: + - patterns: + - pattern: $T + - pattern-inside: | + $T.save + ... + pattern-sinks: + - patterns: + - pattern-inside: | + render $T + message: Found a call to `render $T` after calling `$T.save`. Do not call `render` + after calling `save` on an ActiveRecord object. Reloading the page will cause + the state-changing operation to be repeated which may cause undesirable side + effects. Use `redirect_to` instead. + languages: + - ruby + severity: WARNING + fix: redirect_to $T + metadata: + references: + - https://guides.rubyonrails.org/getting_started.html#creating-a-new-article + category: correctness + technology: + - rails + - ruby + - activerecord +- id: ruby.rails.performance.ruby-rails-performance-indexes-are-really-beneficial.ruby-rails-performance-indexes-are-beneficial + patterns: + - pattern-not-inside: | + add_column $TABLE, $COLUMN, $TYPE, ... + ... + add_index $TABLE, $COLUMN, ... + - pattern: | + add_column $TABLE, $COLUMN, $TYPE, ... + - metavariable-regex: + metavariable: $COLUMN + regex: (.*_id$) + - metavariable-regex: + metavariable: $TYPE + regex: :integer|:bigint + message: >- + The $COLUMN column appears to be a foreign key. Would it benefit from + an index? Having an index can improve performance. + languages: + - ruby + severity: INFO + metadata: + category: performance + technology: + - rails + references: + - https://archive.is/i7SLO +- id: ruby.rails.security.audit.avoid-session-manipulation.avoid-session-manipulation + metadata: + shortDescription: Allowing an attacker to manipulate the session may lead to unintended behavior. + tags: [security] + owasp: + - A01:2021 - Broken Access Control + cwe: + - 'CWE-276: Incorrect Default Permissions' + references: + - https://brakemanscanner.org/docs/warning_types/session_manipulation/ + category: security + technology: + - rails + help: | + ## Remediation + Session manipulation can occur when an application allows user-input in session keys. Since sessions are typically considered a source of truth (e.g. to check the logged-in user or to match CSRF tokens), allowing an attacker to manipulate the session may lead to unintended behavior. + + ## References + [Session Manipulation](https://brakemanscanner.org/docs/warning_types/session_manipulation/) + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + message: >- + This gets data from session using user inputs. A malicious user may be able to retrieve + information from your session that you didn't intend them to. Do not use user input as + a session key. + languages: [ruby] + severity: WARNING + mode: taint + pattern-sources: + - pattern: params + - pattern: cookies + - pattern: request.env + pattern-sinks: + - pattern: session[...] +- id: ruby.rails.security.audit.avoid-tainted-file-access.avoid-tainted-file-access + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - "CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')" + references: + - https://github.com/presidentbeef/brakeman/blob/main/docs/warning_types/file_access/index.markdown + category: security + technology: + - rails + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: HIGH + impact: MEDIUM + confidence: MEDIUM + message: >- + Using user input when accessing files is potentially dangerous. A malicious actor could use this to + modify or access files + they have no right to. + languages: [ruby] + severity: WARNING + mode: taint + pattern-sources: + - pattern: params + - pattern: cookies + - pattern: request.env + pattern-sinks: + - patterns: + - pattern-either: + - pattern: Dir.$X(...) + - pattern: File.$X(...) + - pattern: IO.$X(...) + - pattern: Kernel.$X(...) + - pattern: PStore.$X(...) + - pattern: Pathname.$X(...) + - metavariable-pattern: + metavariable: $X + patterns: + - pattern-either: + - pattern: chdir + - pattern: chroot + - pattern: delete + - pattern: entries + - pattern: foreach + - pattern: glob + - pattern: install + - pattern: lchmod + - pattern: lchown + - pattern: link + - pattern: load + - pattern: load_file + - pattern: makedirs + - pattern: move + - pattern: new + - pattern: open + - pattern: read + - pattern: readlines + - pattern: rename + - pattern: rmdir + - pattern: safe_unlink + - pattern: symlink + - pattern: syscopy + - pattern: sysopen + - pattern: truncate + - pattern: unlink +- id: ruby.rails.security.audit.avoid-tainted-ftp-call.avoid-tainted-ftp-call + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - "CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')" + references: + - https://github.com/presidentbeef/brakeman/blob/main/docs/warning_types/file_access/index.markdown + category: security + technology: + - rails + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: HIGH + impact: MEDIUM + confidence: MEDIUM + message: >- + Using user input when accessing files is potentially dangerous. A malicious actor could use this to + modify or access files + they have no right to. + languages: [ruby] + severity: WARNING + mode: taint + pattern-sources: + - pattern: params + - pattern: cookies + - pattern: request.env + pattern-sinks: + - pattern-either: + - pattern: Net::FTP.$X(...) + - patterns: + - pattern-inside: | + $FTP = Net::FTP.$OPEN(...) + ... + $FTP.$METHOD(...) + - pattern: $FTP.$METHOD(...) +- id: ruby.rails.security.audit.avoid-tainted-http-request.avoid-tainted-http-request + metadata: + owasp: + - A10:2021 - Server-Side Request Forgery (SSRF) + cwe: + - 'CWE-918: Server-Side Request Forgery (SSRF)' + references: + - https://github.com/presidentbeef/brakeman/blob/main/docs/warning_types/file_access/index.markdown + category: security + technology: + - rails + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + impact: MEDIUM + likelihood: MEDIUM + confidence: MEDIUM + message: >- + Using user input when accessing files is potentially dangerous. A malicious actor could use this to + modify or access files + they have no right to. + languages: [ruby] + severity: WARNING + mode: taint + pattern-sources: + - pattern: params + - pattern: cookies + - pattern: request.env + pattern-sinks: + - pattern-either: + - patterns: + - pattern: Net::HTTP::$METHOD.new(...) + - metavariable-pattern: + metavariable: $METHOD + patterns: + - pattern-either: + - pattern: Copy + - pattern: Delete + - pattern: Get + - pattern: Head + - pattern: Lock + - pattern: Mkcol + - pattern: Move + - pattern: Options + - pattern: Patch + - pattern: Post + - pattern: Propfind + - pattern: Proppatch + - pattern: Put + - pattern: Trace + - pattern: Unlock + - patterns: + - pattern: Net::HTTP.$X(...) + - metavariable-pattern: + metavariable: $X + patterns: + - pattern-either: + - pattern: get + - pattern: get2 + - pattern: head + - pattern: head2 + - pattern: options + - pattern: patch + - pattern: post + - pattern: post2 + - pattern: post_form + - pattern: put + - pattern: request + - pattern: request_get + - pattern: request_head + - pattern: request_post + - pattern: send_request + - pattern: trace + - pattern: get_print + - pattern: get_response + - pattern: start +- id: ruby.rails.security.audit.avoid-tainted-shell-call.avoid-tainted-shell-call + metadata: + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + cwe: + - "CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')" + references: + - https://github.com/presidentbeef/brakeman/blob/main/docs/warning_types/file_access/index.markdown + category: security + technology: + - rails + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: HIGH + impact: MEDIUM + confidence: MEDIUM + message: >- + Using user input when accessing files is potentially dangerous. A malicious actor could use this to + modify or access files + they have no right to. + languages: [ruby] + severity: ERROR + mode: taint + pattern-sources: + - pattern-either: + - pattern: params[...] + - pattern: cookies + - pattern: request.env + pattern-sinks: + - patterns: + - pattern-either: + - patterns: + - pattern: Kernel.$X(...) + - patterns: + - pattern-either: + - pattern: Shell.$X(...) + - patterns: + - pattern-inside: | + $SHELL = Shell.$ANY(...) + ... + $SHELL.$X(...) + - pattern: $SHELL.$X(...) + - metavariable-pattern: + metavariable: $X + patterns: + - pattern-either: + - pattern: cat + - pattern: chdir + - pattern: chroot + - pattern: delete + - pattern: entries + - pattern: exec + - pattern: foreach + - pattern: glob + - pattern: install + - pattern: lchmod + - pattern: lchown + - pattern: link + - pattern: load + - pattern: load_file + - pattern: makedirs + - pattern: move + - pattern: new + - pattern: open + - pattern: read + - pattern: readlines + - pattern: rename + - pattern: rmdir + - pattern: safe_unlink + - pattern: symlink + - pattern: syscopy + - pattern: sysopen + - pattern: system + - pattern: truncate + - pattern: unlink +- id: ruby.rails.security.audit.detailed-exceptions.detailed-exceptions + metadata: + owasp: + - A01:2021 - Broken Access Control + cwe: + - 'CWE-200: Exposure of Sensitive Information to an Unauthorized Actor' + source-rule-url: https://github.com/presidentbeef/brakeman/blob/main/lib/brakeman/checks/check_detailed_exceptions.rb + category: security + technology: + - rails + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + message: >- + Found that the setting for providing detailed exception reports in Rails + is set to true. This can lead to information exposure, + where sensitive system or internal information is displayed to the end user. Instead, turn this setting + off. + languages: [ruby] + severity: WARNING + patterns: + - pattern-either: + - patterns: + - pattern: | + config.consider_all_requests_local = true + - patterns: + - pattern-inside: | + class $CONTROLLER < ApplicationController + ... + end + - pattern: | + def show_detailed_exceptions? (...) + ... + return $RETURN + end + - metavariable-pattern: + metavariable: $RETURN + patterns: + - pattern-not: | + false +- id: ruby.rails.security.audit.rails-skip-forgery-protection.rails-skip-forgery-protection + pattern: skip_forgery_protection + message: This call turns off CSRF protection allowing CSRF attacks against the application + languages: + - ruby + severity: WARNING + metadata: + cwe: + - 'CWE-352: Cross-Site Request Forgery (CSRF)' + category: security + technology: + - rails + references: + - https://api.rubyonrails.org/classes/ActionController/RequestForgeryProtection/ClassMethods.html#method-i-skip_forgery_protection + owasp: + - A01:2021 - Broken Access Control + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW +- id: ruby.rails.security.audit.sqli.ruby-pg-sqli.ruby-pg-sqli + mode: taint + pattern-propagators: + - pattern: $X << $Y + from: $Y + to: $X + pattern-sources: + - pattern-either: + - pattern: | + params + - pattern: | + cookies + pattern-sinks: + - patterns: + - pattern-either: + - pattern-inside: | + $CON = PG.connect(...) + ... + - pattern-inside: | + $CON = PG::Connection.open(...) + ... + - pattern-inside: | + $CON = PG::Connection.new(...) + ... + - pattern-either: + - pattern: | + $CON.$METHOD($X,...) + - pattern: | + $CON.$METHOD $X, ... + - focus-metavariable: $X + - metavariable-regex: + metavariable: $METHOD + regex: ^(exec|exec_params)$ + languages: + - ruby + message: >- + Detected string concatenation with a non-literal variable in a pg + Ruby SQL statement. This could lead to SQL injection if the variable is user-controlled + and not properly sanitized. In order to prevent SQL injection, + use parameterized queries or prepared statements instead. + You can use parameterized queries like so: `conn.exec_params('SELECT $1 AS a, $2 AS b, $3 AS c', [1, + 2, nil])` + And you can use prepared statements with `exec_prepared`. + metadata: + cwe: + - "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')" + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + references: + - https://www.rubydoc.info/gems/pg/PG/Connection + category: security + technology: + - rails + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: HIGH + impact: MEDIUM + confidence: MEDIUM + severity: WARNING +- id: ruby.rails.security.audit.xss.avoid-content-tag.avoid-content-tag + metadata: + source-rule-url: https://github.com/presidentbeef/brakeman/blob/main/lib/brakeman/checks/check_content_tag.rb + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + references: + - https://github.com/presidentbeef/brakeman/blob/main/docs/warning_types/template_injection/index.markdown + - https://www.netsparker.com/blog/web-security/preventing-xss-ruby-on-rails-web-applications/ + category: security + technology: + - rails + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + message: >- + 'content_tag()' bypasses HTML escaping for some portion of the content. + If external data can reach here, this exposes your application + to cross-site scripting (XSS) attacks. Ensure no external data reaches here. + If you must do this, create your HTML manually and use 'html_safe'. Ensure no + external data enters the HTML-safe string! + languages: [ruby] + severity: WARNING + pattern: content_tag(...) +- id: ruby.rails.security.audit.xss.avoid-default-routes.avoid-default-routes + metadata: + owasp: + - A01:2021 - Broken Access Control + cwe: + - 'CWE-276: Incorrect Default Permissions' + references: + - https://github.com/presidentbeef/brakeman/blob/main/docs/warning_types/default_routes/index.markdown + category: security + technology: + - rails + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + message: >- + Default routes are enabled in this routes file. This means any public method on a + controller can be called as an action. It is very easy to accidentally expose a + method you didn't mean to. Instead, remove this line and explicitly include all + routes you intend external users to follow. + languages: [ruby] + severity: WARNING + patterns: + - pattern-either: + - pattern: map.connect ":controller/:action/:id" + - pattern: match ':controller(/:action(/:id(.:format)))' + paths: + include: + - '*routes.rb' +- id: ruby.rails.security.audit.xss.avoid-html-safe.avoid-html-safe + metadata: + source-rule-url: https://github.com/presidentbeef/brakeman/blob/main/lib/brakeman/checks/check_cross_site_scripting.rb + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + references: + - https://github.com/presidentbeef/brakeman/blob/main/docs/warning_types/cross_site_scripting/index.markdown + - https://www.netsparker.com/blog/web-security/preventing-xss-ruby-on-rails-web-applications/ + category: security + technology: + - rails + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + message: >- + 'html_safe()' does not make the supplied string safe. 'html_safe()' bypasses + HTML escaping. If external data can reach here, this exposes your application + to cross-site scripting (XSS) attacks. Ensure no external data reaches here. + languages: [ruby] + severity: WARNING + pattern-either: + - pattern: $STR.html_safe + - pattern: $STR.html_safe.$MORE +- id: ruby.rails.security.audit.xss.avoid-link-to.avoid-link-to + metadata: + source-rule-url: https://github.com/presidentbeef/brakeman/blob/main/lib/brakeman/checks/check_link_to.rb + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + references: + - https://brakemanscanner.org/docs/warning_types/link_to/ + - https://brakemanscanner.org/docs/warning_types/link_to_href/ + category: security + technology: + - rails + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: HIGH + impact: MEDIUM + confidence: MEDIUM + message: >- + This code includes user input in `link_to`. In Rails 2.x, the body of `link_to` is not escaped. + This means that user input which reaches the body will be executed when the HTML is rendered. + Even in other versions, values starting with `javascript:` or `data:` are not escaped. + It is better to create and use a safer function which checks the body argument. + languages: [ruby] + severity: WARNING + mode: taint + pattern-sources: + - pattern: params + - pattern: cookies + - pattern: request.env + - pattern-either: + - pattern: $MODEL.url(...) + - pattern: $MODEL.uri(...) + - pattern: $MODEL.link(...) + - pattern: $MODEL.page(...) + - pattern: $MODEL.site(...) + pattern-sinks: + - pattern: link_to(...) + pattern-sanitizers: + - patterns: + - pattern: | + "...#{...}..." + - pattern-not: | + "#{...}..." +- id: ruby.rails.security.audit.xss.avoid-raw.avoid-raw + metadata: + source-rule-url: https://github.com/presidentbeef/brakeman/blob/main/lib/brakeman/checks/check_cross_site_scripting.rb + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + references: + - https://api.rubyonrails.org/classes/ActionView/Helpers/OutputSafetyHelper.html#method-i-raw + - https://www.netsparker.com/blog/web-security/preventing-xss-ruby-on-rails-web-applications/ + category: security + technology: + - rails + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + message: >- + 'raw()' bypasses HTML escaping. If external data can reach here, this exposes your application + to cross-site scripting (XSS) attacks. If you must do this, construct individual strings + and mark them as safe for HTML rendering with `html_safe()`. + languages: [ruby] + severity: WARNING + pattern: raw(...) +- id: ruby.rails.security.audit.xss.avoid-redirect.avoid-redirect + metadata: + owasp: + - A01:2021 - Broken Access Control + cwe: + - "CWE-601: URL Redirection to Untrusted Site ('Open Redirect')" + references: + - https://brakemanscanner.org/docs/warning_types/redirect/ + category: security + technology: + - rails + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + message: >- + When a redirect uses user input, a malicious user can spoof a website under a trusted URL or access + restricted parts of + a site. When using user-supplied values, sanitize the value before using it for the redirect. + languages: [ruby] + severity: WARNING + mode: taint + pattern-sources: + - pattern: params + - pattern: cookies + - pattern: request.env + - patterns: + - pattern: $MODEL.$X(...) + - pattern-not: $MODEL.$X("...") + - metavariable-pattern: + metavariable: $X + pattern-either: + - pattern: all + - pattern: create + - pattern: create! + - pattern: find + - pattern: find_by_sql + - pattern: first + - pattern: last + - pattern: new + - pattern: from + - pattern: group + - pattern: having + - pattern: joins + - pattern: lock + - pattern: order + - pattern: reorder + - pattern: select + - pattern: where + - pattern: find_by + - pattern: find_by! + - pattern: take + pattern-sinks: + - pattern: redirect_to(...) + pattern-sanitizers: + - pattern: params.merge(:only_path => true) + - pattern: params.merge(:host => ...) +- id: ruby.rails.security.audit.xss.avoid-render-dynamic-path.avoid-render-dynamic-path + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - "CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')" + references: + - https://brakemanscanner.org/docs/warning_types/dynamic_render_paths/ + category: security + technology: + - rails + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: HIGH + impact: MEDIUM + confidence: MEDIUM + message: >- + Avoid rendering user input. It may be possible for a malicious user to input a path that lets them + access a template they + shouldn't. To prevent this, check dynamic template paths against a predefined allowlist to make sure + it's an allowed template. + languages: [ruby] + severity: WARNING + mode: taint + pattern-sources: + - pattern: params + - pattern: cookies + - pattern: request.env + pattern-sinks: + - patterns: + - pattern-inside: render($X => $INPUT, ...) + - pattern: $INPUT + - metavariable-pattern: + metavariable: $X + pattern-either: + - pattern: action + - pattern: template + - pattern: partial + - pattern: file +- id: ruby.rails.security.audit.xss.avoid-render-inline.avoid-render-inline + metadata: + source-rule-url: https://github.com/presidentbeef/brakeman/blob/main/lib/brakeman/checks/check_render_inline.rb + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + references: + - https://brakemanpro.com/2017/09/08/cross-site-scripting-in-rails#inline-renders---even-worse-than-xss + category: security + technology: + - rails + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + message: >- + 'render inline: ...' renders an entire ERB template inline and is dangerous. + If external data can reach here, this exposes your application + to server-side template injection (SSTI) or cross-site scripting (XSS) attacks. + Instead, consider using a partial or another safe rendering method. + languages: [ruby] + severity: WARNING + pattern: 'render inline: ...' +- id: ruby.rails.security.audit.xss.avoid-render-text.avoid-render-text + metadata: + source-rule-url: https://github.com/presidentbeef/brakeman/blob/main/lib/brakeman/checks/check_render_inline.rb + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + references: + - https://brakemanpro.com/2017/09/08/cross-site-scripting-in-rails#inline-renders---even-worse-than-xss + category: security + technology: + - rails + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + message: >- + 'render text: ...' actually sets the content-type to 'text/html'. + If external data can reach here, this exposes your application + to cross-site scripting (XSS) attacks. Instead, use 'render plain: ...' to + render non-HTML text. + languages: [ruby] + severity: WARNING + pattern: 'render text: ...' + fix-regex: + regex: 'text:' + replacement: 'plain:' +- id: ruby.rails.security.audit.xss.manual-template-creation.manual-template-creation + metadata: + source-rule-url: https://github.com/presidentbeef/brakeman/blob/main/lib/brakeman/checks/check_template_injection.rb + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + references: + - https://github.com/presidentbeef/brakeman/blob/main/docs/warning_types/template_injection/index.markdown + category: security + technology: + - rails + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + message: >- + Detected manual creation of an ERB template. Manual creation of templates + may expose your application to server-side template injection (SSTI) or + cross-site scripting (XSS) attacks if user input is used to create the + template. Instead, create a '.erb' template file and use 'render'. + languages: [ruby] + severity: WARNING + pattern: ERB.new(...) +- id: ruby.rails.security.audit.xss.templates.alias-for-html-safe.alias-for-html-safe + message: >- + The syntax `<%== ... %>` is an alias for `html_safe`. This means the + content inside these tags will be rendered as raw HTML. This may expose + your application to cross-site scripting. If you need raw HTML, prefer + using the more explicit `html_safe` and be sure to correctly sanitize + variables using a library such as DOMPurify. + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + references: + - https://medium.com/sumone-technical-blog/a-pretty-way-to-unescape-html-in-a-ruby-on-rails-application-efc22b850027 + - https://stackoverflow.com/questions/4251284/raw-vs-html-safe-vs-h-to-unescape-html#:~:text=== + category: security + technology: + - rails + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + languages: [generic] + paths: + include: + - '*.erb' + severity: WARNING + patterns: + - pattern: <%== ... %> + - pattern-not: <%== $...A.to_json %> +- id: ruby.rails.security.audit.xss.templates.avoid-content-tag.avoid-content-tag + message: >- + 'content_tag' exhibits unintuitive escaping behavior and may accidentally + expose your application to cross-site scripting. If using Rails 2, only + attribute values are escaped. If using Rails 3, content and attribute values + are escaped. Tag and attribute names are never escaped. Because of this, + it is recommended to use 'html_safe' if you must render raw HTML data. + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + source-rule-url: https://brakemanscanner.org/docs/warning_types/content_tag/ + references: + - https://brakemanscanner.org/docs/warning_types/content_tag/ + category: security + technology: + - rails + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + languages: [generic] + paths: + include: + - '*.erb' + severity: WARNING + patterns: + - pattern-inside: <%= ... %> + - pattern: content_tag +- id: ruby.rails.security.audit.xss.templates.avoid-html-safe.avoid-html-safe + message: >- + 'html_safe' renders raw HTML. This means that normal + HTML escaping is bypassed. If user data can be controlled here, this + exposes your application to cross-site scripting (XSS). If you need to + do this, be sure to correctly sanitize the data using a library such as + DOMPurify. + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + source-rule-url: https://github.com/presidentbeef/brakeman/blob/main/lib/brakeman/checks/check_cross_site_scripting.rb + references: + - https://stackoverflow.com/questions/4251284/raw-vs-html-safe-vs-h-to-unescape-html#:~:text=== + - https://medium.com/sumone-technical-blog/a-pretty-way-to-unescape-html-in-a-ruby-on-rails-application-efc22b850027 + category: security + technology: + - rails + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + languages: [generic] + paths: + include: + - '*.erb' + severity: WARNING + patterns: + - pattern-inside: <%= ... %> + - pattern: $SOMETHING.html_safe +- id: ruby.rails.security.audit.xss.templates.avoid-raw.avoid-raw + message: >- + 'raw' renders raw HTML, as the name implies. This means that normal + HTML escaping is bypassed. If user data can be controlled here, this + exposes your application to cross-site scripting (XSS). If you need to + do this, be sure to correctly sanitize the data using a library such as + DOMPurify. + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + source-rule-url: https://github.com/presidentbeef/brakeman/blob/main/lib/brakeman/checks/check_cross_site_scripting.rb + references: + - https://stackoverflow.com/questions/4251284/raw-vs-html-safe-vs-h-to-unescape-html#:~:text=== + - https://medium.com/sumone-technical-blog/a-pretty-way-to-unescape-html-in-a-ruby-on-rails-application-efc22b850027 + category: security + technology: + - rails + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + languages: [generic] + paths: + include: + - '*.erb' + severity: WARNING + patterns: + - pattern-inside: <%= ... %> + - pattern: raw +- id: ruby.rails.security.audit.xss.templates.dangerous-link-to.dangerous-link-to + message: >- + Detected a template variable used in 'link_to'. This will + generate dynamic data in the 'href' attribute. + This allows a malicious actor to + input the 'javascript:' URI and is subject to cross- + site scripting (XSS) attacks. If using a relative URL, + start with a literal forward slash and concatenate the URL, + like this: 'link_to "Here", "/"+@link'. You may also consider + setting the Content Security Policy (CSP) header. + metadata: + source-rule-url: https://github.com/presidentbeef/brakeman/blob/main/lib/brakeman/checks/check_link_to.rb + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Ruby_on_Rails_Cheat_Sheet.html#cross-site-scripting-xss + - https://brakemanscanner.org/docs/warning_types/link_to_href/ + category: security + technology: + - rails + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + languages: + - generic + paths: + include: + - '*.erb' + severity: WARNING + patterns: + - pattern-inside: <%= ... %> + - pattern-not-inside: link_to ... "/" + ... @$VAR + - pattern-not-inside: link_to ... '/' + ... @$VAR + - pattern: link_to ... @$VAR +- id: ruby.rails.security.audit.xss.templates.unquoted-attribute.unquoted-attribute + message: 'Detected a unquoted template variable as an attribute. If unquoted, a malicious actor could + inject custom JavaScript handlers. To fix this, add quotes around the template expression, like this: + "<%= expr %>".' + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + references: + - https://brakemanpro.com/2017/09/08/cross-site-scripting-in-rails#unquoted-attributes + - https://flask.palletsprojects.com/en/1.1.x/security/#cross-site-scripting-xss + category: security + technology: + - rails + license: Commons Clause License Condition v1.0[LGPL-2.1-only] + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + languages: + - generic + paths: + include: + - '*.erb' + severity: WARNING + patterns: + - pattern-inside: <$TAG ...> + - pattern-not-inside: ="..." + - pattern-not-inside: ="<%= ... %>" + - pattern-not-inside: ='...' + - pattern-not-inside: ='<%= ... %>' + - pattern: <%= ... %> + fix-regex: + regex: <%=(.*?)%> + replacement: '"<%=\1%>"' +- id: ruby.rails.security.audit.xss.templates.var-in-href.var-in-href + message: >- + Detected a template variable used in an anchor tag with + the 'href' attribute. This allows a malicious actor to + input the 'javascript:' URI and is subject to cross- + site scripting (XSS) attacks. If using a relative URL, + start with a literal forward slash and concatenate the URL, + like this: href='/<%= link =>'. You may also consider setting + the Content Security Policy (CSP) header. + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + references: + - https://flask.palletsprojects.com/en/1.1.x/security/#cross-site-scripting-xss#:~:text=javascript:%20URI + - https://github.com/pugjs/pug/issues/2952 + category: security + technology: + - rails + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + languages: + - generic + paths: + include: + - '*.erb' + severity: WARNING + pattern-either: + - pattern: + - pattern: +- id: ruby.rails.security.audit.xss.templates.var-in-script-tag.var-in-script-tag + message: >- + Detected a template variable used in a script tag. + Although template variables are HTML escaped, HTML + escaping does not always prevent cross-site scripting (XSS) + attacks when used directly in JavaScript. If you need to do + this, use `escape_javascript` or its alias, `j`. However, this + will not protect from XSS in all circumstances; see the references + for more information. Consider placing this value in the HTML + portion (outside of a script tag). + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + references: + - https://www.netsparker.com/blog/web-security/preventing-xss-ruby-on-rails-web-applications/ + - https://www.youtube.com/watch?v=yYTkLUEdIyE + - https://www.veracode.com/blog/secure-development/nodejs-template-engines-why-default-encoders-are-not-enough + category: security + technology: + - rails + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + languages: + - generic + paths: + include: + - '*.erb' + severity: WARNING + patterns: + - pattern-inside: + - pattern-not: <%= j ... > + - pattern-not: <%= escape_javascript ... > + - pattern: <%= ... > +- id: ruby.rails.security.audit.xxe.libxml-backend.libxml-backend + languages: [ruby] + pattern: ActiveSupport::XmlMini.backend = "LibXML" + severity: WARNING + message: >- + This application is using LibXML as the XML backend. LibXML can be vulnerable to + XML External Entities (XXE) vulnerabilities. Use the built-in Rails XML parser, REXML, + instead. + metadata: + references: + - https://www.stackhawk.com/blog/rails-xml-external-entities-xxe-guide-examples-and-prevention/ + - https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html + technology: + - rails + - libxml + category: security + cwe: + - 'CWE-611: Improper Restriction of XML External Entity Reference' + owasp: + - A04:2017 - XML External Entities (XXE) + - A05:2021 - Security Misconfiguration + confidence: LOW + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM +- id: ruby.rails.security.audit.xxe.xml-external-entities-enabled.xml-external-entities-enabled + languages: [ruby] + patterns: + - pattern-either: + - pattern-inside: | + LibXML::XML.class_eval do + ... + end + - pattern-inside: | + XML.class_eval do + ... + end + - pattern: XML.default_substitute_entities = true + severity: ERROR + message: >- + This application is explicitly enabling external entities enabling an attacker to inject + malicious XML to exploit an XML External Entities (XXE) vulnerability. This could let the + attacker cause a denial-of-service by forcing the parser to parse large files, or at worst, + let the attacker download sensitive files or user data. Use the built-in Rails XML parser, + REXML, instead. + metadata: + references: + - https://www.stackhawk.com/blog/rails-xml-external-entities-xxe-guide-examples-and-prevention/ + - https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html + technology: + - rails + - libxml + category: security + cwe: + - 'CWE-611: Improper Restriction of XML External Entity Reference' + owasp: + - A04:2017 - XML External Entities (XXE) + - A05:2021 - Security Misconfiguration + confidence: LOW + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH +- id: ruby.rails.security.brakeman.check-before-filter.check-before-filter + mode: search + patterns: + - pattern-either: + - pattern: | + skip_filter ..., :except => $ARGS + - pattern: | + skip_before_filter ..., :except => $ARGS + - pattern: | + skip_before_action ..., :except => $ARGS + message: 'Disabled-by-default Rails controller checks make it much easier to introduce access control + mistakes. Prefer an allowlist approach with `:only => [...]` rather than `except: => [...]`' + languages: + - ruby + severity: ERROR + metadata: + source-rule-url: https://github.com/presidentbeef/brakeman/blob/main/lib/brakeman/checks/check_skip_before_filter.rb + category: security + cwe: + - 'CWE-284: Improper Access Control' + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + technology: + - ruby + - rails + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - vuln + impact: MEDIUM + likelihood: MEDIUM + confidence: MEDIUM +- id: ruby.rails.security.brakeman.check-cookie-store-session-security-attributes.check-cookie-store-session-security-attributes + patterns: + - pattern-either: + - patterns: + - pattern: | + :$KEY => false + - pattern-inside: | + ActionController::Base.session = {...} + - pattern: | + $MODULE::Application.config.session_store :cookie_store, ..., :$KEY => false, ... + - pattern: | + $CLASS.application.config.session_store :cookie_store, ..., $KEY: false, ... + - metavariable-regex: + metavariable: $KEY + regex: ^(session_)?(http_?only|secure)$ + message: Found a Rails `cookie_store` session configuration setting the `$KEY` attribute to `false`. + If using a cookie-based session store, the HttpOnly and Secure flags should be set. + languages: + - ruby + severity: WARNING + metadata: + source-rule-url: https://github.com/presidentbeef/brakeman/blob/main/lib/brakeman/checks/check_session_settings.rb + category: security + cwe: + - "CWE-1004: Sensitive Cookie Without 'HttpOnly' Flag" + owasp: + - A05:2021 - Security Misconfiguration + technology: + - ruby + - rails + references: + - https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/06-Session_Management_Testing/02-Testing_for_Cookies_Attributes + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW +- id: ruby.rails.security.brakeman.check-dynamic-render-local-file-include.check-dynamic-render-local-file-include + mode: search + paths: + include: + - '*.erb' + patterns: + - pattern: | + params[...] + - pattern-inside: | + render :file => ... + message: Found request parameters in a call to `render` in a dynamic context. This can allow end users + to request arbitrary local files which may result in leaking sensitive information persisted on disk. + languages: + - generic + severity: WARNING + metadata: + technology: + - ruby + - rails + category: security + cwe: + - "CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')" + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + source-rule-url: https://github.com/presidentbeef/brakeman/blob/main/lib/brakeman/checks/check_render.rb + references: + - https://owasp.org/www-project-web-security-testing-guide/v42/4-Web_Application_Security_Testing/07-Input_Validation_Testing/11.1-Testing_for_Local_File_Inclusion + - https://github.com/presidentbeef/brakeman/blob/f74cb53ead47f0af821d98b5b41e16d63100c240/test/apps/rails2/app/views/home/test_render.html.erb + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM +- id: ruby.rails.security.brakeman.check-http-verb-confusion.check-http-verb-confusion + mode: search + patterns: + - pattern: | + if request.get? + ... + else + ... + end + - pattern-not-inside: | + if ... + elsif ... + ... + end + message: Found an improperly constructed control flow block with `request.get?`. Rails will route HEAD + requests as GET requests but they will fail the `request.get?` check, potentially causing unexpected + behavior unless an `elif` condition is used. + languages: + - ruby + severity: ERROR + metadata: + source-rule-url: https://github.com/presidentbeef/brakeman/blob/main/lib/brakeman/checks/check_verb_confusion.rb + category: security + cwe: + - 'CWE-650: Trusting HTTP Permission Methods on the Server Side' + owasp: + - A04:2021 - Insecure Design + technology: + - ruby + - rails + references: + - https://github.com/presidentbeef/brakeman/blob/main/test/apps/rails6/app/controllers/accounts_controller.rb + subcategory: + - vuln + likelihood: HIGH + impact: MEDIUM + confidence: MEDIUM +- id: ruby.rails.security.brakeman.check-permit-attributes-high.check-permit-attributes-high + patterns: + - pattern: $P.permit($ATTRIBUTE) + - metavariable-regex: + metavariable: $ATTRIBUTE + regex: .*(admin|account_id).* + message: Calling `permit` on security-critical properties like `$ATTRIBUTE` may leave your application + vulnerable to mass assignment. + languages: + - ruby + severity: ERROR + metadata: + source-rule-url: https://github.com/presidentbeef/brakeman/blob/main/lib/brakeman/checks/check_permit_attributes.rb + category: security + cwe: + - 'CWE-915: Improperly Controlled Modification of Dynamically-Determined Object Attributes' + owasp: + - A08:2021 - Software and Data Integrity Failures + technology: + - ruby + - rails + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Mass_Assignment_Cheat_Sheet.html + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW +- id: ruby.rails.security.brakeman.check-permit-attributes-medium.check-permit-attributes-medium + patterns: + - pattern: $P.permit($ATTRIBUTE) + - metavariable-regex: + metavariable: $ATTRIBUTE + regex: .*(role|banned).* + message: Calling `permit` on security-critical properties like `$ATTRIBUTE` may leave your application + vulnerable to mass assignment. + languages: + - ruby + severity: WARNING + metadata: + source-rule-url: https://github.com/presidentbeef/brakeman/blob/main/lib/brakeman/checks/check_permit_attributes.rb + category: security + cwe: + - 'CWE-915: Improperly Controlled Modification of Dynamically-Determined Object Attributes' + owasp: + - A08:2021 - Software and Data Integrity Failures + technology: + - ruby + - rails + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Mass_Assignment_Cheat_Sheet.html + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + +- id: ruby.rails.security.brakeman.check-rails-secret-yaml.check-rails-secret-yaml + paths: + include: + - '*secrets.*.yml' + - '*secrets.*.yaml' + patterns: + - pattern: | + secret_key_base: $VALUE + - metavariable-pattern: + metavariable: $VALUE + language: generic + patterns: + - pattern-not: | + <%= ... %> + - pattern-inside: | + production: + ... + message: $VALUE Found a string literal assignment to a production Rails session secret in `secrets.yaml`. + Do not commit secret values to source control! Any user in possession of this value may falsify arbitrary + session data in your application. Read this value from an environment variable, KMS, or file on disk + outside of source control. + languages: + - yaml + severity: WARNING + metadata: + source-rule-url: https://github.com/presidentbeef/brakeman/blob/main/lib/brakeman/checks/check_session_settings.rb + category: security + cwe: + - 'CWE-540: Inclusion of Sensitive Information in Source Code' + owasp: + - A01:2021 - Broken Access Control + technology: + - ruby + - rails + references: + - https://github.com/presidentbeef/brakeman/blob/main/test/apps/rails4/config/secrets.yml + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW +- id: ruby.rails.security.brakeman.check-rails-session-secret-handling.check-rails-session-secret-handling + patterns: + - pattern-either: + - patterns: + - pattern: | + :$KEY => "$LITERAL" + - pattern-inside: | + ActionController::Base.session = {...} + - pattern: | + $RAILS::Application.config.$KEY = "$LITERAL" + - pattern: | + Rails.application.config.$KEY = "$LITERAL" + - metavariable-regex: + metavariable: $KEY + regex: ^secret(_(token|key_base))?$ + message: Found a string literal assignment to a Rails session secret `$KEY`. Do not commit secret values + to source control! Any user in possession of this value may falsify arbitrary session data in your + application. Read this value from an environment variable, KMS, or file on disk outside of source + control. + languages: + - ruby + severity: WARNING + metadata: + source-rule-url: https://github.com/presidentbeef/brakeman/blob/main/lib/brakeman/checks/check_session_settings.rb + category: security + cwe: + - 'CWE-540: Inclusion of Sensitive Information in Source Code' + owasp: + - A01:2021 - Broken Access Control + technology: + - ruby + - rails + references: + - https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/06-Session_Management_Testing/02-Testing_for_Cookies_Attributes + - https://github.com/presidentbeef/brakeman/blob/main/test/apps/rails4_with_engines/config/initializers/secret_token.rb + - https://github.com/presidentbeef/brakeman/blob/main/test/apps/rails3/config/initializers/secret_token.rb + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM +- id: ruby.rails.security.brakeman.check-redirect-to.check-redirect-to + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - pattern: params + - pattern: cookies + - pattern: request.env + - pattern: url_for(params[...],...,:only_path => false,...) + pattern-sanitizers: + - patterns: + - pattern-either: + - patterns: + - pattern: | + $F(...) + - metavariable-pattern: + metavariable: $F + patterns: + - pattern-not-regex: (params|url_for|cookies|request.env|permit|redirect_to) + - pattern: | + params.merge! :only_path => true + ... + - pattern: | + params.slice(...) + ... + - pattern: | + redirect_to [...] + - patterns: + - pattern: | + $MODEL. ... .$M(...) + ... + - metavariable-regex: + metavariable: $MODEL + regex: '[A-Z]\w+' + - metavariable-regex: + metavariable: $M + regex: (all|create|find|find_by|find_by_sql|first|last|new|from|group|having|joins|lock|order|reorder|select|where|take) + - patterns: + - pattern: | + params.$UNSAFE_HASH.merge(...,:only_path => true,...) + ... + - metavariable-regex: + metavariable: $UNSAFE_HASH + regex: to_unsafe_h(ash)? + - patterns: + - pattern: params.permit(...,$X,...) + - metavariable-pattern: + metavariable: $X + patterns: + - pattern-not-regex: (host|port|(sub)?domain) + pattern-sinks: + - patterns: + - pattern: $X + - pattern-inside: | + redirect_to $X, ... + - pattern-not-regex: params\.\w+(? true` hash value. + languages: + - ruby + severity: WARNING + metadata: + source-rule-url: https://github.com/presidentbeef/brakeman/blob/main/lib/brakeman/checks/check_redirect.rb + category: security + cwe: + - "CWE-601: URL Redirection to Untrusted Site ('Open Redirect')" + technology: + - ruby + - rails + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html + owasp: + - A01:2021 - Broken Access Control + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM +- id: ruby.rails.security.brakeman.check-regex-dos.check-regex-dos + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - pattern: | + cookies[...] + - patterns: + - pattern: | + cookies. ... .$PROPERTY[...] + - metavariable-regex: + metavariable: $PROPERTY + regex: (?!signed|encrypted) + - pattern: | + params[...] + - pattern: | + request.env[...] + - patterns: + - pattern: $Y + - pattern-either: + - pattern-inside: | + $RECORD.read_attribute($Y) + - pattern-inside: | + $RECORD[$Y] + - metavariable-regex: + metavariable: $RECORD + regex: '[A-Z][a-z]+' + pattern-sinks: + - patterns: + - pattern-either: + - patterns: + - pattern: $Y + - pattern-inside: | + /...#{...}.../ + - patterns: + - pattern: $Y + - pattern-inside: | + Regexp.new(...) + message: >- + Found a potentially user-controllable argument in the construction of a regular expressions. + This may result in excessive resource consumption when applied to certain inputs, or when the user + is allowed to control the match target. + Avoid allowing users to specify regular expressions processed by the server. + If you must support user-controllable input in a regular expression, use an allow-list to restrict + the expressions users may supply to limit catastrophic backtracking. + languages: + - ruby + severity: ERROR + metadata: + source-rule-url: https://github.com/presidentbeef/brakeman/blob/main/lib/brakeman/checks/check_regex_dos.rb + category: security + cwe: + - 'CWE-1333: Inefficient Regular Expression Complexity' + owasp: + - A03:2017 - Sensitive Data Exposure + technology: + - ruby + - rails + references: + - https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS + subcategory: + - vuln + likelihood: HIGH + impact: MEDIUM + confidence: MEDIUM +- id: ruby.rails.security.brakeman.check-render-local-file-include.check-render-local-file-include + mode: taint + pattern-sources: + - patterns: + - pattern: params[...] + pattern-sinks: + - patterns: + - pattern-either: + - pattern: | + render ..., file: $X + - pattern: | + render ..., inline: $X + - pattern: | + render ..., template: $X + - pattern: | + render ..., action: $X + - pattern: | + render $X, ... + - focus-metavariable: $X + pattern-sanitizers: + - patterns: + - pattern: $MAP[...] + - metavariable-pattern: + metavariable: $MAP + patterns: + - pattern-not-regex: params + - pattern: File.basename(...) + message: Found request parameters in a call to `render`. This can allow end + users to request arbitrary local files which may result in leaking + sensitive information persisted on disk. Where possible, avoid letting + users specify template paths for `render`. If you must allow user input, + use an allow-list of known templates or normalize the user-supplied value + with `File.basename(...)`. + languages: + - ruby + severity: WARNING + metadata: + technology: + - ruby + - rails + category: security + cwe: + - "CWE-22: Improper Limitation of a Pathname to a Restricted Directory + ('Path Traversal')" + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + source-rule-url: https://github.com/presidentbeef/brakeman/blob/main/lib/brakeman/checks/check_render.rb + references: + - https://owasp.org/www-project-web-security-testing-guide/v42/4-Web_Application_Security_Testing/07-Input_Validation_Testing/11.1-Testing_for_Local_File_Inclusion + - https://github.com/presidentbeef/brakeman/blob/f74cb53/test/apps/rails2/app/controllers/home_controller.rb#L48-L60 + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: HIGH + confidence: MEDIUM + license: Commons Clause License Condition v1.0[LGPL-2.1-only] + vulnerability_class: + - Path Traversal + +- id: ruby.rails.security.brakeman.check-reverse-tabnabbing.check-reverse-tabnabbing + mode: search + paths: + include: + - '*.erb' + patterns: + - pattern: | + _blank + - pattern-inside: | + target: ... + - pattern-not-inside: | + <%= ... rel: 'noopener noreferrer' ...%> + - pattern-either: + - patterns: + - pattern-inside: | + <%= $...INLINERUBYDO do -%> + ... + <% end %> + - metavariable-pattern: + metavariable: $...INLINERUBYDO + language: ruby + patterns: + - pattern: | + link_to ... + - pattern-not: | + link_to "...", "...", ... + - patterns: + - pattern-not-inside: | + <%= ... do - %> + - pattern-inside: | + <%= $...INLINERUBY %> + - metavariable-pattern: + metavariable: $...INLINERUBY + language: ruby + patterns: + - pattern: | + link_to ... + - pattern-not: | + link_to '...', '...', ... + - pattern-not: | + link_to '...', target: ... + message: Setting an anchor target of `_blank` without the `noopener` or `noreferrer` attribute allows + reverse tabnabbing on Internet Explorer, Opera, and Android Webview. + languages: + - generic + severity: WARNING + metadata: + source-rule-url: https://github.com/presidentbeef/brakeman/blob/main/lib/brakeman/checks/check_reverse_tabnabbing.rb + category: security + cwe: + - 'CWE-1022: Use of Web Link to Untrusted Target with window.opener Access' + technology: + - ruby + - rails + references: + - https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#browser_compatibility + - https://github.com/presidentbeef/brakeman/blob/3f5d5d5/test/apps/rails5/app/views/users/show.html.erb + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM +- id: ruby.rails.security.brakeman.check-secrets.check-secrets + patterns: + - pattern: $VAR = "$VALUE" + - metavariable-regex: + metavariable: $VAR + regex: (?i)password|secret|(rest_auth_site|api)_key$ + - metavariable-regex: + metavariable: $VALUE + regex: .+ + message: >- + Found a Brakeman-style secret - a variable with the name password/secret/api_key/rest_auth_site_key + and a non-empty string literal value. + languages: + - ruby + severity: WARNING + metadata: + technology: + - ruby + - rails + category: security + cwe: + - 'CWE-200: Exposure of Sensitive Information to an Unauthorized Actor' + owasp: + - A01:2021 - Broken Access Control + source-rule-url: https://github.com/presidentbeef/brakeman/blob/main/lib/brakeman/checks/check_secrets.rb + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + - https://github.com/presidentbeef/brakeman/blob/3f5d5d5f00864cdf7769c50f5bd26f1769a4ba75/test/apps/rails3.1/app/controllers/users_controller.rb + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM +- id: ruby.rails.security.brakeman.check-send-file.check-send-file + mode: taint + pattern-sources: + - pattern-either: + - pattern: | + cookies[...] + - patterns: + - pattern: | + cookies. ... .$PROPERTY[...] + - metavariable-regex: + metavariable: $PROPERTY + regex: (?!signed|encrypted) + - pattern: | + params[...] + - pattern: | + request.env[...] + pattern-sinks: + - patterns: + - pattern: | + send_file ... + message: Allowing user input to `send_file` allows a malicious user to potentially read arbitrary files + from the server. Avoid accepting user input in `send_file` or normalize with `File.basename(...)` + languages: + - ruby + severity: ERROR + metadata: + source-rule-url: https://github.com/presidentbeef/brakeman/blob/main/lib/brakeman/checks/check_send_file.rb + category: security + cwe: + - 'CWE-73: External Control of File Name or Path' + owasp: + - A04:2021 - Insecure Design + technology: + - ruby + - rails + references: + - https://owasp.org/www-community/attacks/Path_Traversal + - https://owasp.org/Top10/A01_2021-Broken_Access_Control/ + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM +- id: ruby.rails.security.brakeman.check-sql.check-sql + mode: taint + pattern-sources: + - pattern-either: + - pattern: | + cookies[...] + - patterns: + - pattern: | + cookies. ... .$PROPERTY[...] + - metavariable-regex: + metavariable: $PROPERTY + regex: (?!signed|encrypted) + - pattern: | + params[...] + - pattern: | + request.env[...] + pattern-sanitizers: + - patterns: + - pattern-either: + - patterns: + - pattern: $X + - pattern-either: + - pattern-inside: | + :$KEY => $X + - pattern-inside: | + ["...",$X,...] + - pattern: | + params[...].to_i + - pattern: | + params[...].to_f + - patterns: + - pattern: | + params[...] ? $A : $B + - metavariable-pattern: + metavariable: $A + patterns: + - pattern-not: | + params[...] + - metavariable-pattern: + metavariable: $B + patterns: + - pattern-not: | + params[...] + pattern-sinks: + - patterns: + - pattern: $X + - pattern-not-inside: | + $P.where("...",...) + - pattern-not-inside: | + $P.where(:$KEY => $VAL,...) + - pattern-either: + - pattern-inside: | + $P.$M(...) + - pattern-inside: | + $P.$M("...",...) + - pattern-inside: | + class $P < ActiveRecord::Base + ... + end + - metavariable-regex: + metavariable: $M + regex: (where|find|first|last|select|minimum|maximum|calculate|sum|average) + message: Found potential SQL injection due to unsafe SQL query construction via $X. Where possible, + prefer parameterized queries. + languages: + - ruby + severity: ERROR + metadata: + source-rule-url: https://github.com/presidentbeef/brakeman/blob/main/lib/brakeman/checks/check_sql.rb + category: security + cwe: + - "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')" + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + technology: + - ruby + - rails + references: + - https://owasp.org/www-community/attacks/SQL_Injection + - https://github.com/presidentbeef/brakeman/blob/main/test/apps/rails3.1/app/models/product.rb + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM +- id: ruby.rails.security.brakeman.check-unsafe-reflection-methods.check-unsafe-reflection-methods + mode: taint + pattern-sources: + - pattern-either: + - pattern: | + cookies[...] + - patterns: + - pattern: | + cookies. ... .$PROPERTY[...] + - metavariable-regex: + metavariable: $PROPERTY + regex: (?!signed|encrypted) + - pattern: | + params[...] + - pattern: | + request.env[...] + pattern-sinks: + - patterns: + - pattern: $X + - pattern-either: + - pattern-inside: | + $X. ... .to_proc + - patterns: + - pattern-inside: | + $Y.method($Z) + - focus-metavariable: $Z + - patterns: + - pattern-inside: | + $Y.tap($Z) + - focus-metavariable: $Z + - patterns: + - pattern-inside: | + $Y.tap{ |$ANY| $Z } + - focus-metavariable: $Z + message: Found user-controllable input to a reflection method. This may allow a user to alter program + behavior and potentially execute arbitrary instructions in the context of the process. Do not provide + arbitrary user input to `tap`, `method`, or `to_proc` + languages: + - ruby + severity: ERROR + metadata: + source-rule-url: https://github.com/presidentbeef/brakeman/blob/main/lib/brakeman/checks/check_unsafe_reflection_methods.rb + category: security + cwe: + - "CWE-94: Improper Control of Generation of Code ('Code Injection')" + owasp: + - A03:2021 - Injection + technology: + - ruby + - rails + references: + - https://github.com/presidentbeef/brakeman/blob/main/test/apps/rails6/app/controllers/groups_controller.rb + cwe2022-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM +- id: ruby.rails.security.brakeman.check-unsafe-reflection.check-unsafe-reflection + mode: taint + pattern-sources: + - pattern-either: + - pattern: | + cookies[...] + - patterns: + - pattern: | + cookies. ... .$PROPERTY[...] + - metavariable-regex: + metavariable: $PROPERTY + regex: (?!signed|encrypted) + - pattern: | + params[...] + - pattern: | + request.env[...] + pattern-sinks: + - patterns: + - pattern: $X + - pattern-either: + - pattern-inside: | + $X.constantize + - pattern-inside: | + $X. ... .safe_constantize + - pattern-inside: | + const_get(...) + - pattern-inside: | + qualified_const_get(...) + message: Found user-controllable input to Ruby reflection functionality. This allows a remote user + to influence runtime behavior, up to and including arbitrary remote code execution. Do not provide + user-controllable input to reflection functionality. Do not call symbol conversion on user-controllable + input. + languages: + - ruby + severity: ERROR + metadata: + source-rule-url: https://github.com/presidentbeef/brakeman/blob/main/lib/brakeman/checks/check_unsafe_reflection.rb + category: security + cwe: + - "CWE-94: Improper Control of Generation of Code ('Code Injection')" + owasp: + - A03:2021 - Injection + technology: + - ruby + - rails + references: + - https://github.com/presidentbeef/brakeman/blob/main/test/apps/rails2/app/controllers/application_controller.rb + cwe2022-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM +- id: ruby.rails.security.brakeman.check-unscoped-find.check-unscoped-find + mode: taint + pattern-sources: + - pattern-either: + - pattern: | + cookies[...] + - patterns: + - pattern: | + cookies. ... .$PROPERTY[...] + - metavariable-regex: + metavariable: $PROPERTY + regex: (?!signed|encrypted) + - pattern: | + params[...] + - pattern: | + request.env[...] + pattern-sinks: + - patterns: + - pattern-either: + - pattern: $MODEL.find(...) + - pattern: $MODEL.find_by_id(...) + - pattern: $MODEL.find_by_id!(...) + - metavariable-regex: + metavariable: $MODEL + regex: '[A-Z]\S+' + message: Found an unscoped `find(...)` with user-controllable input. If the ActiveRecord model being + searched against is sensitive, this may lead to Insecure Direct Object Reference (IDOR) behavior and + allow users to read arbitrary records. Scope the find to the current user, e.g. `current_user.accounts.find(params[:id])`. + languages: + - ruby + severity: WARNING + metadata: + source-rule-url: https://github.com/presidentbeef/brakeman/blob/main/lib/brakeman/checks/check_unscoped_find.rb + category: security + cwe: + - 'CWE-639: Authorization Bypass Through User-Controlled Key' + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + technology: + - ruby + - rails + references: + - https://brakemanscanner.org/docs/warning_types/unscoped_find/ + - https://github.com/presidentbeef/brakeman/blob/main/test/apps/rails3.1/app/controllers/users_controller.rb + subcategory: + - vuln + likelihood: MEDIUM + impact: HIGH + confidence: MEDIUM +- id: ruby.rails.security.brakeman.check-validation-regex.check-validation-regex + mode: search + patterns: + - pattern-either: + - pattern: | + validates ..., :format => <... $V ...>,... + - pattern: | + validates_format_of ..., :with => <... $V ...>,... + - metavariable-regex: + metavariable: $V + regex: /(.{2}(? ...`. Ruby regex behavior is multiline by default and lines should be terminated by `\A` for beginning + of line and `\Z` for end of line, respectively. + languages: + - ruby + severity: ERROR + metadata: + source-rule-url: https://github.com/presidentbeef/brakeman/blob/main/lib/brakeman/checks/check_validation_regex.rb + category: security + cwe: + - 'CWE-185: Incorrect Regular Expression' + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + technology: + - ruby + - rails + references: + - https://brakemanscanner.org/docs/warning_types/format_validation/ + - https://github.com/presidentbeef/brakeman/blob/aef6253a8b7bcb97116f2af1ed2a561a6ae35bd5/test/apps/rails3/app/models/account.rb + - https://github.com/presidentbeef/brakeman/blob/main/test/apps/rails3.1/app/models/account.rb + subcategory: + - vuln + impact: MEDIUM + likelihood: MEDIUM + confidence: MEDIUM +- id: ruby.rails.security.injection.raw-html-format.raw-html-format + languages: [ruby] + severity: WARNING + message: >- + Detected user input flowing into a manually constructed HTML string. You may be accidentally bypassing + secure methods + of rendering HTML by manually constructing HTML and this could create a cross-site scripting vulnerability, + which could + let attackers steal sensitive user data. Use the `render template` and make template files which will + safely render HTML + instead, or inspect that the HTML is absolutely rendered safely with a function like `sanitize`. + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + category: security + technology: + - rails + references: + - https://www.netsparker.com/blog/web-security/preventing-xss-ruby-on-rails-web-applications/ + - https://api.rubyonrails.org/classes/ActionView/Helpers/SanitizeHelper.html + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: HIGH + impact: MEDIUM + confidence: MEDIUM + mode: taint + pattern-sanitizers: + - pattern-either: + - pattern: sanitize(...) + - pattern: strip_tags(...) + pattern-sources: + - patterns: + - pattern-either: + - pattern: params + - pattern: request + pattern-sinks: + - patterns: + - pattern-either: + - patterns: + - pattern: | + $HTMLSTR + - pattern-regex: <\w+.* + - patterns: + - pattern-either: + - pattern: Kernel::sprintf("$HTMLSTR", ...) + - pattern: | + "$HTMLSTR" + $EXPR + - pattern: | + "$HTMLSTR" % $EXPR + - metavariable-pattern: + metavariable: $HTMLSTR + language: generic + pattern: <$TAG ... +- id: ruby.rails.security.injection.tainted-sql-string.tainted-sql-string + languages: + - ruby + severity: ERROR + message: Detected user input used to manually construct a SQL string. This is usually bad practice because + manual construction could accidentally result in a SQL injection. An attacker could use a SQL injection + to steal or modify contents of the database. Instead, use a parameterized query which is available + by default in most database engines. Alternatively, consider using an object-relational mapper (ORM) + such as ActiveRecord which will protect your queries. + metadata: + cwe: + - "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')" + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + category: security + technology: + - rails + references: + - https://rorsecurity.info/portfolio/ruby-on-rails-sql-injection-cheat-sheet + license: Commons Clause License Condition v1.0[LGPL-2.1-only] + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: HIGH + confidence: MEDIUM + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - pattern: params + - pattern: request + pattern-sanitizers: + - pattern: | + $PARAMS.slice(...) + pattern-sinks: + - patterns: + - pattern-either: + - patterns: + - pattern-either: + - patterns: + - pattern: | + $RECORD.where($X,...) + + - pattern: | + $RECORD.find(..., :conditions => $X,...) + - focus-metavariable: $X + - patterns: + - pattern: | + "$SQLVERB#{$EXPR}..." + - pattern-not-inside: | + $FUNC("...", "...#{$EXPR}...",...) + - focus-metavariable: $SQLVERB + - pattern-regex: (?i)(select|delete|insert|create|update|alter|drop)\b + - patterns: + - pattern-either: + - pattern: Kernel::sprintf("$SQLSTR", $EXPR) + - pattern: | + "$SQLSTR" + $EXPR + - pattern: | + "$SQLSTR" % $EXPR + - pattern-not-inside: | + $FUNC("...", "...#{$EXPR}...",...) + - focus-metavariable: $EXPR + - metavariable-regex: + metavariable: $SQLSTR + regex: (?i)(select|delete|insert|create|update|alter|drop)\b +- id: ruby.rails.security.injection.tainted-url-host.tainted-url-host + languages: [ruby] + severity: WARNING + message: >- + User data flows into the host portion of this manually-constructed URL. + This could allow an attacker to send data to their own server, potentially + exposing sensitive data such as cookies or authorization information sent + with this request. They could also probe internal servers or other resources + that the server running this code can access. (This is called server-side + request forgery, or SSRF.) Do not allow arbitrary hosts. Use the `ssrf_filter` + gem and guard the url construction with `SsrfFilter(...)`, or create + an allowlist for approved hosts. + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + category: security + technology: + - rails + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet.html + - https://github.com/arkadiyt/ssrf_filter + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: HIGH + confidence: MEDIUM + mode: taint + pattern-sanitizers: + - pattern: SsrfFilter + pattern-sources: + - patterns: + - pattern-either: + - pattern: params + - pattern: request + pattern-sinks: + - patterns: + - pattern-either: + - patterns: + - pattern: | + $URLSTR + - pattern-regex: \w+:\/\/#{.*} + - patterns: + - pattern-either: + - pattern: Kernel::sprintf("$URLSTR", ...) + - pattern: | + "$URLSTR" + $EXPR + - pattern: | + "$URLSTR" % $EXPR + - metavariable-pattern: + metavariable: $URLSTR + language: generic + pattern: $SCHEME:// ... +- id: rust.lang.security.args-os.args-os + message: >- + args_os should not be used for security operations. From the docs: + "The first element is traditionally the path of the executable, but it + can be set to arbitrary text, and might not even exist. This means this + property should not be relied upon for security purposes." + pattern: "std::env::args_os()" + metadata: + references: + - https://doc.rust-lang.org/stable/std/env/fn.args_os.html + technology: + - rust + category: security + cwe: "CWE-807: Reliance on Untrusted Inputs in a Security Decision" + confidence: HIGH + likelihood: LOW + impact: LOW + subcategory: audit + languages: [rust] + severity: INFO +- id: rust.lang.security.args.args + message: >- + args should not be used for security operations. From the docs: + "The first element is traditionally the path of the executable, but it + can be set to arbitrary text, and might not even exist. This means this + property should not be relied upon for security purposes." + pattern: "std::env::args()" + metadata: + references: + - https://doc.rust-lang.org/stable/std/env/fn.args.html + technology: + - rust + category: security + cwe: "CWE-807: Reliance on Untrusted Inputs in a Security Decision" + confidence: HIGH + likelihood: LOW + impact: LOW + subcategory: audit + languages: [rust] + severity: INFO +- id: rust.lang.security.current-exe.current-exe + message: >- + current_exe should not be used for security operations. From the docs: + "The output of this function should not be trusted for anything that + might have security implications. Basically, if users can run the + executable, they can change the output arbitrarily." + pattern: "std::env::current_exe()" + metadata: + references: + - https://doc.rust-lang.org/stable/std/env/fn.current_exe.html#security + technology: + - rust + category: security + cwe: "CWE-807: Reliance on Untrusted Inputs in a Security Decision" + confidence: HIGH + likelihood: LOW + impact: LOW + subcategory: audit + languages: [rust] + severity: INFO +- id: rust.lang.security.insecure-hashes.insecure-hashes + message: Detected cryptographically insecure hashing function + pattern-either: + - pattern: "md2::Md2::new(...)" + - pattern: "md4::Md4::new(...)" + - pattern: "md5::Md5::new(...)" + - pattern: "sha1::Sha1::new(...)" + metadata: + references: + - https://github.com/RustCrypto/hashes + - https://docs.rs/md2/latest/md2/ + - https://docs.rs/md4/latest/md4/ + - https://docs.rs/md5/latest/md5/ + - https://docs.rs/sha-1/latest/sha1/ + technology: + - rust + category: security + cwe: "CWE-328: Use of Weak Hash" + confidence: HIGH + likelihood: LOW + impact: MEDIUM + subcategory: audit + languages: [rust] + severity: WARNING +- id: rust.lang.security.reqwest-accept-invalid.reqwest-accept-invalid + message: Dangerously accepting invalid TLS information + pattern-either: + - pattern: reqwest::Client::builder(). ... .danger_accept_invalid_hostnames(true) + - pattern: reqwest::Client::builder(). ... .danger_accept_invalid_certs(true) + metadata: + references: + - https://docs.rs/reqwest/latest/reqwest/struct.ClientBuilder.html#method.danger_accept_invalid_hostnames + - https://docs.rs/reqwest/latest/reqwest/struct.ClientBuilder.html#method.danger_accept_invalid_certs + technology: + - reqwest + category: security + cwe: "CWE-295: Improper Certificate Validation" + confidence: HIGH + likelihood: LOW + impact: MEDIUM + subcategory: vuln + languages: [rust] + severity: WARNING +- id: rust.lang.security.reqwest-set-sensitive.reqwest-set-sensitive + message: Set sensitive flag on security headers with 'set_sensitive' to treat data with special care + patterns: + - pattern: | + let mut $HEADERS = header::HeaderMap::new(); + ... + let $HEADER_VALUE = <... header::HeaderValue::$FROM_FUNC(...) ...>; + ... + $HEADERS.insert($HEADER, $HEADER_VALUE); + - pattern-not: | + let mut $HEADERS = header::HeaderMap::new(); + ... + let $HEADER_VALUE = <... header::HeaderValue::$FROM_FUNC(...) ...>; + ... + $HEADER_VALUE.set_sensitive(true); + ... + $HEADERS.insert($HEADER, $HEADER_VALUE); + - metavariable-pattern: + metavariable: $FROM_FUNC + pattern-either: + - pattern: from_static + - pattern: from_str + - pattern: from_name + - pattern: from_bytes + - pattern: from_maybe_shared + - metavariable-pattern: + metavariable: $HEADER + pattern-either: + - pattern: header::AUTHORIZATION + - pattern: '"Authorization"' + metadata: + references: + - https://docs.rs/reqwest/latest/reqwest/header/struct.HeaderValue.html#method.set_sensitive + technology: + - reqwest + category: security + cwe: "CWE-921: Storage of Sensitive Data in a Mechanism without Access Control" + confidence: MEDIUM + likelihood: LOW + impact: LOW + subcategory: audit + languages: [rust] + severity: INFO +- id: rust.lang.security.rustls-dangerous.rustls-dangerous + message: Dangerous client config used, ensure SSL verification + pattern-either: + - pattern: "rustls::client::DangerousClientConfig" + - pattern: "$CLIENT.dangerous().set_certificate_verifier(...)" + - pattern: | + let $CLIENT = rustls::client::ClientConfig::dangerous(...); + ... + $CLIENT.set_certificate_verifier(...); + metadata: + references: + - https://docs.rs/rustls/latest/rustls/client/struct.DangerousClientConfig.html + - https://docs.rs/rustls/latest/rustls/client/struct.ClientConfig.html#method.dangerous + technology: + - rustls + category: security + cwe: "CWE-295: Improper Certificate Validation" + confidence: HIGH + likelihood: LOW + impact: MEDIUM + subcategory: vuln + languages: [rust] + severity: WARNING +- id: rust.lang.security.ssl-verify-none.ssl-verify-none + message: SSL verification disabled, this allows for MitM attacks + pattern: "$BUILDER.set_verify(openssl::ssl::SSL_VERIFY_NONE)" + metadata: + references: + - https://docs.rs/openssl/latest/openssl/ssl/struct.SslContextBuilder.html#method.set_verify + technology: + - openssl + category: security + cwe: "CWE-295: Improper Certificate Validation" + confidence: HIGH + likelihood: LOW + impact: MEDIUM + subcategory: vuln + languages: [rust] + severity: WARNING +- id: rust.lang.security.temp-dir.temp-dir + message: >- + temp_dir should not be used for security operations. From the docs: + 'The temporary directory may be shared among users, or between processes + with different privileges; thus, the creation of any files or directories + in the temporary directory must use a secure method to create a uniquely + named file. Creating a file or directory with a fixed or predictable name + may result in “insecure temporary file” security vulnerabilities.' + pattern: "std::env::temp_dir()" + metadata: + references: + - https://doc.rust-lang.org/stable/std/env/fn.temp_dir.html + technology: + - rust + category: security + cwe: "CWE-807: Reliance on Untrusted Inputs in a Security Decision" + confidence: HIGH + likelihood: LOW + impact: LOW + subcategory: audit + languages: [rust] + severity: INFO +- id: rust.lang.security.unsafe-usage.unsafe-usage + message: Detected 'unsafe' usage, please audit for secure usage + pattern: "unsafe { ... }" + metadata: + references: + - https://doc.rust-lang.org/std/keyword.unsafe.html + technology: + - rust + category: security + cwe: "CWE-242: Use of Inherently Dangerous Function" + confidence: HIGH + likelihood: LOW + impact: LOW + subcategory: audit + languages: [rust] + severity: INFO +- id: scala.jwt-scala.security.jwt-scala-hardcode.jwt-scala-hardcode + patterns: + - pattern-inside: | + import pdi.jwt.$DEPS + ... + - pattern-either: + - pattern: $JWT.encode($X, "...", ...) + - pattern: $JWT.decode($X, "...", ...) + - pattern: $JWT.decodeRawAll($X, "...", ...) + - pattern: $JWT.decodeRaw($X, "...", ...) + - pattern: $JWT.decodeAll($X, "...", ...) + - pattern: $JWT.validate($X, "...", ...) + - pattern: $JWT.isValid($X, "...", ...) + - pattern: $JWT.decodeJson($X, "...", ...) + - pattern: $JWT.decodeJsonAll($X, "...", ...) + - patterns: + - pattern-either: + - pattern: $JWT.encode($X, $KEY, ...) + - pattern: $JWT.decode($X, $KEY, ...) + - pattern: $JWT.decodeRawAll($X, $KEY, ...) + - pattern: $JWT.decodeRaw($X, $KEY, ...) + - pattern: $JWT.decodeAll($X, $KEY, ...) + - pattern: $JWT.validate($X, $KEY, ...) + - pattern: $JWT.isValid($X, $KEY, ...) + - pattern: $JWT.decodeJson($X, $KEY, ...) + - pattern: $JWT.decodeJsonAll($X, $KEY, ...) + - pattern: $JWT.encode($X, this.$KEY, ...) + - pattern: $JWT.decode($X, this.$KEY, ...) + - pattern: $JWT.decodeRawAll($X, this.$KEY, ...) + - pattern: $JWT.decodeRaw($X, this.$KEY, ...) + - pattern: $JWT.decodeAll($X, this.$KEY, ...) + - pattern: $JWT.validate($X, this.$KEY, ...) + - pattern: $JWT.isValid($X, this.$KEY, ...) + - pattern: $JWT.decodeJson($X, this.$KEY, ...) + - pattern: $JWT.decodeJsonAll($X, this.$KEY, ...) + - pattern-either: + - pattern-inside: | + class $CL { + ... + $KEY = "..." + ... + } + - pattern-inside: | + object $CL { + ... + $KEY = "..." + ... + } + - metavariable-pattern: + metavariable: $JWT + patterns: + - pattern-either: + - pattern: Jwt + - pattern: JwtArgonaut + - pattern: JwtCirce + - pattern: JwtJson4s + - pattern: JwtJson + - pattern: JwtUpickle + message: >- + Hardcoded JWT secret or private key is used. + This is a Insufficiently Protected Credentials weakness: https://cwe.mitre.org/data/definitions/522.html + Consider using an appropriate security mechanism to protect the credentials (e.g. keeping secrets + in environment variables) + languages: [scala] + severity: WARNING + metadata: + references: + - https://jwt-scala.github.io/jwt-scala/ + category: security + cwe: + - 'CWE-522: Insufficiently Protected Credentials' + owasp: + - A02:2017 - Broken Authentication + - A04:2021 - Insecure Design + technology: + - scala + confidence: HIGH + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM +- id: scala.lang.correctness.positive-number-index-of.positive-number-index-of + metadata: + category: correctness + technology: + - scala + license: Commons Clause License Condition v1.0[LGPL-2.1-only] + references: + - https://blog.codacy.com/9-scala-security-issues/ + confidence: MEDIUM + message: >- + Flags scala code that look for values that are greater than 0. This ignores the first element, which is most likely a + bug. Instead, use indexOf with -1. If the intent is to check the inclusion of a value, use the contains method instead. + severity: WARNING + languages: + - scala + patterns: + - pattern-either: + - patterns: + - pattern: | + $OBJ.indexOf(...) > $VALUE + - metavariable-comparison: + metavariable: $VALUE + comparison: $VALUE >= 0 + - patterns: + - pattern: | + $OBJ.indexOf(...) >= $SMALLERVAL + - metavariable-comparison: + metavariable: $SMALLERVAL + comparison: $SMALLERVAL > 0 +- id: scala.lang.security.audit.dangerous-seq-run.dangerous-seq-run + patterns: + - pattern: Seq($CMD, ...) + - pattern-not: Seq("...", ...) + - pattern-inside: | + import sys.process + ... + - pattern-not-inside: | + $CMD = "..." + ... + - pattern-either: + - pattern-inside: Seq(...).! + - pattern-inside: Seq(...).!! + - pattern-inside: Seq(...).lazyLines + message: >- + Found dynamic content used for the external process. + This is dangerous if arbitrary data can reach this function call because it allows a malicious actor + to execute commands. + Ensure your variables are not controlled by users or sufficiently sanitized. + languages: [scala] + severity: ERROR + metadata: + category: security + cwe: + - "CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')" + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + technology: + - scala + confidence: LOW + references: + - https://owasp.org/Top10/A03_2021-Injection + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH +- id: scala.lang.security.audit.dangerous-shell-run.dangerous-shell-run + patterns: + - pattern: Seq($SH, "-c", $CMD, ...) + - pattern-not: Seq($SH, "-c", "...", ...) + - pattern-inside: | + import sys.process + ... + - pattern-not-inside: | + $CMD = "..." + ... + - pattern-either: + - pattern-inside: Seq(...).! + - pattern-inside: Seq(...).!! + - pattern-inside: Seq(...).lazyLines + - metavariable-regex: + metavariable: $SH + regex: '"(sh|bash|ksh|csh|tcsh|zsh)"' + message: >- + Found dynamic content used for the external process. + This is dangerous if arbitrary data can reach this function call because it allows a malicious actor + to execute commands. + Ensure your variables are not controlled by users or sufficiently sanitized. + languages: [scala] + severity: ERROR + metadata: + category: security + cwe: + - "CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')" + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + technology: + - scala + confidence: LOW + references: + - https://owasp.org/Top10/A03_2021-Injection + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH +- id: scala.lang.security.audit.dispatch-ssrf.dispatch-ssrf + patterns: + - pattern: url($URL) + - pattern-inside: | + import dispatch._ + ... + - pattern-either: + - pattern-inside: | + def $FUNC(..., $URL: $T, ...) = $A { + ... + } + - pattern-inside: | + def $FUNC(..., $URL: $T, ...) = { + ... + } + message: >- + A parameter being passed directly into `url` most likely lead to SSRF. + This could allow an attacker to send data to their own server, potentially exposing sensitive data + sent with this request. + They could also probe internal servers or other resources that the server running this code can access. + Do not allow arbitrary hosts. Instead, create an allowlist for approved hosts, or hardcode the correct + host. + metadata: + cwe: + - 'CWE-918: Server-Side Request Forgery (SSRF)' + owasp: + - A10:2021 - Server-Side Request Forgery (SSRF) + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet.html + - https://dispatchhttp.org/Dispatch.html + category: security + technology: + - scala + - dispatch + confidence: LOW + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH + languages: [scala] + severity: WARNING +- id: scala.lang.security.audit.documentbuilder-dtd-enabled.documentbuilder-dtd-enabled + patterns: + - pattern-either: + - pattern: | + $DF = DocumentBuilderFactory.newInstance(...) + ... + $DB = $DF.newDocumentBuilder(...) + - patterns: + - pattern: $DB = DocumentBuilderFactory.newInstance(...) + - pattern-not-inside: | + ... + $X = $DB.newDocumentBuilder(...) + - pattern: $DB = DocumentBuilderFactory.newInstance(...).newDocumentBuilder(...) + - pattern-not-inside: | # nosemgrep: slow-pattern-top-ellipsis + ... + $DB.setXIncludeAware(true) + ... + $DB.setNamespaceAware(true) + ... + $DB.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true) + ... + $DB.setFeature("http://xml.org/sax/features/external-general-entities", false) + ... + $DB.setFeature("http://xml.org/sax/features/external-parameter-entities", false) + - pattern-not-inside: | # nosemgrep: slow-pattern-top-ellipsis + ... + $DB.setXIncludeAware(true) + ... + $DB.setNamespaceAware(true) + ... + $DB.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true) + ... + $DB.setFeature("http://xml.org/sax/features/external-parameter-entities", false) + ... + $DB.setFeature("http://xml.org/sax/features/external-general-entities", false) + - pattern-not-inside: | # nosemgrep: slow-pattern-top-ellipsis + ... + $DB.setXIncludeAware(true) + ... + $DB.setNamespaceAware(true) + ... + $DB.setFeature("http://xml.org/sax/features/external-general-entities", false) + ... + $DB.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true) + ... + $DB.setFeature("http://xml.org/sax/features/external-parameter-entities", false) + - pattern-not-inside: | # nosemgrep: slow-pattern-top-ellipsis + ... + $DB.setXIncludeAware(true) + ... + $DB.setNamespaceAware(true) + ... + $DB.setFeature("http://xml.org/sax/features/external-general-entities", false) + ... + $DB.setFeature("http://xml.org/sax/features/external-parameter-entities", false) + ... + $DB.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true) + message: >- + Document Builder being instantiated without calling the `setFeature` functions that are generally + used for disabling entity processing. + User controlled data in XML Document builder can result in XML Internal Entity Processing vulnerabilities + like the disclosure of confidential data, denial of service, Server Side Request Forgery (SSRF), port + scanning. + Make sure to disable entity processing functionality. + languages: [scala] + severity: WARNING + metadata: + cwe: + - 'CWE-611: Improper Restriction of XML External Entity Reference' + owasp: + - A04:2017 - XML External Entities (XXE) + - A05:2021 - Security Misconfiguration + source-rule-url: https://cheatsheetseries.owasp.org//cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html + category: security + technology: + - scala + confidence: HIGH + references: + - https://owasp.org/Top10/A05_2021-Security_Misconfiguration + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: LOW + impact: MEDIUM +- id: scala.lang.security.audit.insecure-random.insecure-random + metadata: + cwe: + - 'CWE-330: Use of Insufficiently Random Values' + owasp: + - A02:2021 - Cryptographic Failures + category: security + technology: + - scala + - cryptography + license: Commons Clause License Condition v1.0[LGPL-2.1-only] + resources: + - https://find-sec-bugs.github.io/bugs.htm + confidence: LOW + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + message: >- + Flags the use of a predictable random value from `scala.util.Random`. This can lead to vulnerabilities + when used in security + contexts, such as in a CSRF token, password reset token, or any other secret value. To fix this, use + java.security.SecureRandom + instead. + severity: WARNING + languages: + - scala + patterns: + - pattern: | + import scala.util.Random +- id: scala.lang.security.audit.io-source-ssrf.io-source-ssrf + patterns: + - pattern-either: + - pattern: Source.fromURL($URL,...) + - pattern: Source.fromURI($URL,...) + - pattern-inside: | + import scala.io.$SOURCE + ... + - pattern-either: + - pattern-inside: | + def $FUNC(..., $URL: $T, ...) = $A { + ... + } + - pattern-inside: | + def $FUNC(..., $URL: $T, ...) = { + ... + } + message: >- + A parameter being passed directly into `fromURL` most likely lead to SSRF. + This could allow an attacker to send data to their own server, potentially exposing sensitive data + sent with this request. + They could also probe internal servers or other resources that the server running this code can access. + Do not allow arbitrary hosts. Instead, create an allowlist for approved hosts, or hardcode the correct + host. + metadata: + cwe: + - 'CWE-918: Server-Side Request Forgery (SSRF)' + owasp: + - A10:2021 - Server-Side Request Forgery (SSRF) + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet.html + - https://www.scala-lang.org/api/current/scala/io/Source$.html#fromURL(url:java.net.URL)(implicitcodec:scala.io.Codec):scala.io.BufferedSource + category: security + technology: + - scala + confidence: MEDIUM + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH + languages: [scala] + severity: WARNING +- id: scala.lang.security.audit.path-traversal-fromfile.path-traversal-fromfile + metadata: + cwe: + - "CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')" + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + category: security + technology: + - scala + license: Commons Clause License Condition v1.0[LGPL-2.1-only] + resources: + - https://find-sec-bugs.github.io/bugs.htm + confidence: LOW + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + message: >- + Flags cases of possible path traversal. If an unfiltered parameter is passed into 'fromFile', file + from an arbitrary filesystem + location could be read. This could lead to sensitive data exposure and other provles. Instead, sanitize + the user input + instead of performing direct string concatenation. + severity: WARNING + languages: + - scala + patterns: + - pattern-either: + - patterns: + - pattern-either: + - pattern-inside: | + $FILENAME = "..." + $VAR + ... + - pattern-inside: | + $FILENAME = $VAR + "..." + ... + - pattern-inside: | + $FILENAME = $STR.concat($VAR) + ... + - pattern-inside: | + $FILENAME = "...".format(..., $VAR, ...) + ... + - pattern: Source.fromFile($FILENAME, ...) + - patterns: + - pattern-either: + - pattern: Source.fromFile("..." + $VAR, ...) + - pattern: Source.fromFile($VAR + "...", ...) + - pattern: Source.fromFile($STR.concat($VAR), ...) + - pattern: Source.fromFile("...".format(..., $VAR, ...), ...) + - pattern-inside: | + def $FUNC(..., $VAR: $TYPE, ...) = Action { + ... + } +- id: scala.lang.security.audit.rsa-padding-set.rsa-padding-set + metadata: + cwe: + - 'CWE-780: Use of RSA Algorithm without OAEP' + owasp: + - A02:2021 - Cryptographic Failures + category: security + technology: + - scala + - cryptography + license: Commons Clause License Condition v1.0[LGPL-2.1-only] + resources: + - https://blog.codacy.com/9-scala-security-issues/ + confidence: HIGH + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - audit + likelihood: MEDIUM + impact: MEDIUM + message: >- + Usage of RSA without OAEP (Optimal Asymmetric Encryption Padding) may weaken encryption. This could + lead to sensitive data + exposure. Instead, use RSA with `OAEPWithMD5AndMGF1Padding` instead. + severity: WARNING + languages: + - scala + patterns: + - pattern: | + $VAR = $CIPHER.getInstance($MODE) + - metavariable-regex: + metavariable: $MODE + regex: .*RSA/.*/NoPadding.* +- id: scala.lang.security.audit.sax-dtd-enabled.sax-dtd-enabled + patterns: + - pattern-either: + - pattern: $SR = new SAXReader(...) + - pattern: | + $SF = SAXParserFactory.newInstance(...) + ... + $SR = $SF.newSAXParser(...) + - patterns: + - pattern: $SR = SAXParserFactory.newInstance(...) + - pattern-not-inside: | # nosemgrep: slow-pattern-top-ellipsis + ... + $X = $SR.newSAXParser(...) + - pattern: $SR = SAXParserFactory.newInstance(...).newSAXParser(...) + - pattern: $SR = new SAXBuilder(...) + - pattern-not-inside: | # nosemgrep: slow-pattern-top-ellipsis + ... + $SR.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true) + ... + $SR.setFeature("http://xml.org/sax/features/external-general-entities", false) + ... + $SR.setFeature("http://xml.org/sax/features/external-parameter-entities", false) + - pattern-not-inside: | # nosemgrep: slow-pattern-top-ellipsis + ... + $SR.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true) + ... + $SR.setFeature("http://xml.org/sax/features/external-parameter-entities", false) + ... + $SR.setFeature("http://xml.org/sax/features/external-general-entities", false) + - pattern-not-inside: | # nosemgrep: slow-pattern-top-ellipsis + ... + $SR.setFeature("http://xml.org/sax/features/external-general-entities", false) + ... + $SR.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true) + ... + $SR.setFeature("http://xml.org/sax/features/external-parameter-entities", false) + - pattern-not-inside: | # nosemgrep: slow-pattern-top-ellipsis + ... + $SR.setFeature("http://xml.org/sax/features/external-general-entities", false) + ... + $SR.setFeature("http://xml.org/sax/features/external-parameter-entities", false) + ... + $SR.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true) + message: >- + XML processor being instantiated without calling the `setFeature` functions that are generally used + for disabling entity processing. + User controlled data in XML Parsers can result in XML Internal Entity Processing vulnerabilities like + the disclosure of confidential data, denial of service, Server Side Request Forgery (SSRF), port scanning. + Make sure to disable entity processing functionality. + languages: [scala] + severity: WARNING + metadata: + cwe: + - 'CWE-611: Improper Restriction of XML External Entity Reference' + owasp: + - A04:2017 - XML External Entities (XXE) + - A05:2021 - Security Misconfiguration + source-rule-url: https://cheatsheetseries.owasp.org//cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html + category: security + technology: + - scala + confidence: HIGH + references: + - https://owasp.org/Top10/A05_2021-Security_Misconfiguration + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: MEDIUM + impact: MEDIUM +- id: scala.lang.security.audit.scala-dangerous-process-run.scala-dangerous-process-run + patterns: + - pattern-either: + - pattern: $X.! + - pattern: $X.!! + - pattern: $X.lazyLines + - pattern-inside: | + import sys.process + ... + - pattern-not: | + "...".! + - pattern-not: | + "...".!! + - pattern-not: | + "...".lazyLines + - pattern-not: | + Seq(...).! + - pattern-not: | + Seq(...).!! + - pattern-not: | + Seq(...).lazyLines + - pattern-not-inside: | + val $X = "..." + ... + - pattern-not-inside: | + val $X = Seq(...) + ... + message: >- + Found dynamic content used for the external process. + This is dangerous if arbitrary data can reach this function call because it allows a malicious actor + to execute commands. + Use `Seq(...)` for dynamically generated commands. + languages: [scala] + severity: ERROR + metadata: + category: security + cwe: + - "CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')" + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + technology: + - scala + confidence: LOW + references: + - https://owasp.org/Top10/A03_2021-Injection + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM +- id: scala.lang.security.audit.scalac-debug.scalac-debug + patterns: + - pattern-either: + - pattern: scalacOptions ... "-Vdebug" + - pattern: scalacOptions ... "-Ydebug" + message: >- + Scala applications built with `debug` set to true in production may leak debug information to attackers. + Debug mode also affects performance and reliability. + Remove it from configuration. + languages: [generic] + severity: WARNING + paths: + include: + - '*.sbt*' + metadata: + category: security + cwe: + - 'CWE-489: Active Debug Code' + owasp: 'A05:2021 - Security Misconfiguration' + technology: + - scala + - sbt + references: + - https://docs.scala-lang.org/overviews/compiler-options/index.html + confidence: MEDIUM + subcategory: + - audit + likelihood: LOW + impact: LOW +- id: scala.lang.security.audit.scalaj-http-ssrf.scalaj-http-ssrf + patterns: + - pattern: Http($URL) + - pattern-inside: | + import scalaj.http.$HTTP + ... + - pattern-either: + - pattern-inside: | + def $FUNC(..., $URL: $T, ...) = $A { + ... + } + - pattern-inside: | + def $FUNC(..., $URL: $T, ...) = { + ... + } + message: >- + A parameter being passed directly into `Http` can likely lead to SSRF. + This could allow an attacker to send data to their own server, potentially exposing sensitive data + sent with this request. + They could also probe internal servers or other resources that the server running this code can access. + Do not allow arbitrary hosts. Instead, create an allowlist for approved hosts, or hardcode the correct + host. + metadata: + cwe: + - 'CWE-918: Server-Side Request Forgery (SSRF)' + owasp: + - A10:2021 - Server-Side Request Forgery (SSRF) + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet.html + - https://github.com/scalaj/scalaj-http#simplified-http + category: security + technology: + - scala + - scalaj-http + confidence: LOW + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH + languages: [scala] + severity: WARNING +- id: scala.lang.security.audit.scalajs-eval.scalajs-eval + mode: taint + pattern-sources: + - patterns: + - pattern: $PARAM + - pattern-either: + - pattern-inside: | + def $CTRL(..., $PARAM: $TYPE, ...) = { + ... + } + - pattern-inside: | + def $CTRL(..., $PARAM: $TYPE, ...) = $A { + ... + } + - pattern-inside: | + def $CTRL(..., $PARAM: $TYPE, ...) = $A(...) { + ... + } + pattern-sinks: + - patterns: + - pattern: $JS.eval(...) + - pattern-inside: | + import scala.scalajs.$X + ... + message: >- + `eval()` function evaluates JavaScript code represented as a string. Executing JavaScript from a string + is an enormous security risk. + It is far too easy for a bad actor to run arbitrary code when you use `eval()`. + Do not use eval(). Alternatively: Ensure evaluated content is not definable by external sources. + If it’s not possible, strip everything except alphanumeric characters from an input provided for the + command string and arguments. + metadata: + references: + - https://www.scala-js.org/doc/ + cwe: + - "CWE-94: Improper Control of Generation of Code ('Code Injection')" + owasp: + - A03:2021 - Injection + category: security + technology: + - scala + - scala-js + confidence: LOW + cwe2022-top25: true + subcategory: + - vuln + likelihood: LOW + impact: HIGH + languages: [scala] + severity: WARNING +- id: scala.lang.security.audit.tainted-sql-string.tainted-sql-string + languages: + - scala + severity: ERROR + mode: taint + message: User data flows into this manually-constructed SQL string. User data can be safely inserted + into SQL strings using prepared statements or an object-relational mapper (ORM). Manually-constructed + SQL strings is a possible indicator of SQL injection, which could let an attacker steal or manipulate + data from the database. Instead, use prepared statements (`connection.PreparedStatement`) or a safe + library. + metadata: + cwe: + - "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')" + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + references: + - https://docs.oracle.com/javase/7/docs/api/java/sql/PreparedStatement.html + category: security + technology: + - scala + confidence: MEDIUM + license: Commons Clause License Condition v1.0[LGPL-2.1-only] + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: HIGH + pattern-sources: + - patterns: + - pattern: $PARAM + - pattern-either: + - pattern-inside: | + def $CTRL(..., $PARAM: $TYPE, ...) = { + ... + } + - pattern-inside: | + def $CTRL(..., $PARAM: $TYPE, ...) = $A { + ... + } + - pattern-inside: | + def $CTRL(..., $PARAM: $TYPE, ...) = $A(...) { + ... + } + pattern-sinks: + - patterns: + - pattern-either: + - patterns: + - pattern-either: + - pattern: | + "$SQLSTR" + ... + - pattern: | + "$SQLSTR".format(...) + - patterns: + - pattern-inside: | + $SB = new StringBuilder("$SQLSTR"); + ... + - pattern: $SB.append(...) + - patterns: + - pattern-inside: | + $VAR = "$SQLSTR" + ... + - pattern: $VAR += ... + - metavariable-regex: + metavariable: $SQLSTR + regex: (?i)(select|delete|insert|create|update|alter|drop)\b + - patterns: + - pattern-either: + - pattern: s"..." + - pattern: f"..." + - pattern-regex: | + .*\b(?i)(select|delete|insert|create|update|alter|drop)\b.* + - pattern-not-inside: println(...) + pattern-sanitizers: + - pattern-either: + - patterns: + - pattern-either: + - pattern: $LOGGER.$METHOD(...) + - pattern: $LOGGER(...) + - metavariable-regex: + metavariable: $LOGGER + regex: (i?)log.* + - patterns: + - pattern: $LOGGER.$METHOD(...) + - metavariable-regex: + metavariable: $METHOD + regex: (i?)(trace|info|warn|warning|warnToError|error|debug) +- id: scala.lang.security.audit.xmlinputfactory-dtd-enabled.xmlinputfactory-dtd-enabled + patterns: + - pattern-not-inside: | # nosemgrep: slow-pattern-top-ellipsis + ... + $XMLFACTORY.setProperty("javax.xml.stream.isSupportingExternalEntities", false) + - pattern-either: + - pattern: $XMLFACTORY = XMLInputFactory.newFactory(...) + - pattern: $XMLFACTORY = XMLInputFactory.newInstance(...) + - pattern: $XMLFACTORY = new XMLInputFactory(...) + message: >- + XMLInputFactory being instantiated without calling the setProperty functions that are generally used + for disabling entity processing. + User controlled data in XML Document builder can result in XML Internal Entity Processing vulnerabilities + like the disclosure of confidential data, denial of service, Server Side Request Forgery (SSRF), port + scanning. + Make sure to disable entity processing functionality. + languages: [scala] + severity: WARNING + metadata: + cwe: + - 'CWE-611: Improper Restriction of XML External Entity Reference' + owasp: + - A04:2017 - XML External Entities (XXE) + - A05:2021 - Security Misconfiguration + source-rule-url: https://cheatsheetseries.owasp.org//cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html + category: security + technology: + - scala + confidence: HIGH + references: + - https://owasp.org/Top10/A05_2021-Security_Misconfiguration + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM +- id: scala.play.security.conf-csrf-headers-bypass.conf-csrf-headers-bypass + patterns: + - pattern-either: + - pattern: X-Requested-With = "*" + - pattern: Csrf-Token = "..." + - pattern-inside: | + bypassHeaders {... + ... + ...} + - pattern-not-inside: | + {... + ... + ...blackList = [..."application/x-www-form-urlencoded"..."multipart/form-data"..."text/plain"...] + ... + ...} + - pattern-not-inside: | + {... + ... + ...blackList = [..."application/x-www-form-urlencoded"..."text/plain"..."multipart/form-data"...] + ... + ...} + - pattern-not-inside: | + {... + ... + ...blackList = [..."multipart/form-data"..."application/x-www-form-urlencoded"..."text/plain"...] + ... + ...} + - pattern-not-inside: | + {... + ... + ...blackList = [..."multipart/form-data"..."text/plain"..."application/x-www-form-urlencoded"...] + ... + ...} + - pattern-not-inside: | + {... + ... + ...blackList = [..."text/plain"..."application/x-www-form-urlencoded"..."multipart/form-data"...] + ... + ...} + - pattern-not-inside: | + {... + ... + ...blackList = [..."text/plain"..."multipart/form-data"..."application/x-www-form-urlencoded"...] + ... + ...} + message: >- + Possibly bypassable CSRF configuration found. + CSRF is an attack that forces an end user to execute unwanted actions on a web application in which + they’re currently authenticated. + Make sure that Content-Type black list is configured and CORS filter is turned on. + languages: [generic] + severity: ERROR + paths: + include: + - '*.conf' + metadata: + references: + - https://www.playframework.com/documentation/2.8.x/Migration25#CSRF-changes + - https://owasp.org/www-community/attacks/csrf + cwe: + - 'CWE-352: Cross-Site Request Forgery (CSRF)' + owasp: + - A01:2021 - Broken Access Control + category: security + technology: + - scala + - play + confidence: MEDIUM + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: LOW + impact: LOW +- id: scala.play.security.conf-insecure-cookie-settings.conf-insecure-cookie-settings + patterns: + - pattern: secure = false + - pattern-inside: | + session = { + ... + } + message: >- + Session cookie `Secure` flag is explicitly disabled. + The `secure` flag for cookies prevents the client from transmitting + the cookie over insecure channels such as HTTP. Set the `Secure` + flag by setting `secure` to `true` in configuration file. + languages: + - generic + severity: WARNING + paths: + include: + - '*.conf' + metadata: + category: security + references: + - https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#security + - https://www.playframework.com/documentation/2.8.x/SettingsSession#Session-Configuration + technology: + - play + - scala + cwe: + - "CWE-614: Sensitive Cookie in HTTPS Session Without 'Secure' Attribute" + owasp: + - A05:2021 - Security Misconfiguration + confidence: MEDIUM + subcategory: + - vuln + likelihood: LOW + impact: LOW +- id: scala.play.security.tainted-html-response.tainted-html-response + mode: taint + metadata: + category: security + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + technology: + - scala + - play + confidence: MEDIUM + references: + - https://owasp.org/Top10/A03_2021-Injection + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: HIGH + impact: MEDIUM + message: >- + Detected a request with potential user-input going into an `Ok()` response. This bypasses any view + or template environments, including HTML escaping, which may + expose this application to cross-site scripting (XSS) vulnerabilities. + Consider using a view technology such as Twirl which automatically escapes HTML views. + pattern-sources: + - patterns: + - pattern-either: + - patterns: + - pattern: $REQ + - pattern-either: + - pattern-inside: | + Action { + $REQ: Request[$T] => + ... + } + - pattern-inside: | + Action(...) { + $REQ: Request[$T] => + ... + } + - pattern-inside: | + Action.async { + $REQ: Request[$T] => + ... + } + - pattern-inside: | + Action.async(...) { + $REQ: Request[$T] => + ... + } + - patterns: + - pattern: $PARAM + - pattern-either: + - pattern-inside: | + def $CTRL(..., $PARAM: $TYPE, ...) = Action { + ... + } + - pattern-inside: | + def $CTRL(..., $PARAM: $TYPE, ...) = Action(...) { + ... + } + - pattern-inside: | + def $CTRL(..., $PARAM: $TYPE, ...) = Action.async { + ... + } + - pattern-inside: | + def $CTRL(..., $PARAM: $TYPE, ...) = Action.async(...) { + ... + } + pattern-sanitizers: + - pattern-either: + - pattern: org.apache.commons.lang3.StringEscapeUtils.escapeHtml4(...) + - pattern: org.owasp.encoder.Encode.forHtml(...) + pattern-sinks: + - pattern-either: + - pattern: Html.apply(...) + - pattern: Ok(...).as(HTML) + - pattern: Ok(...).as(ContentTypes.HTML) + - patterns: + - pattern: Ok(...).as($CTYPE) + - metavariable-regex: + metavariable: $CTYPE + regex: '"[tT][eE][xX][tT]/[hH][tT][mM][lL]"' + - patterns: + - pattern: Ok(...).as($CTYPE) + - pattern-not: Ok(...).as("...") + - pattern-either: + - pattern-inside: | + def $FUNC(..., $URL: $T, ...) = $A { + ... + } + - pattern-inside: | + def $FUNC(..., $URL: $T, ...) = { + ... + } + severity: WARNING + languages: + - scala +- id: scala.play.security.tainted-slick-sqli.tainted-slick-sqli + mode: taint + metadata: + references: + - https://scala-slick.org/doc/3.3.3/sql.html#splicing-literal-values + - https://scala-slick.org/doc/3.2.0/sql-to-slick.html#non-optimal-sql-code + category: security + cwe: + - "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')" + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + technology: + - scala + - slick + - play + confidence: HIGH + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: HIGH + impact: MEDIUM + message: >- + Detected a tainted SQL statement. This could lead to SQL + injection if variables in the SQL statement are not properly sanitized. + Avoid using using user input for generating SQL strings. + pattern-sources: + - patterns: + - pattern-either: + - patterns: + - pattern: $REQ + - pattern-either: + - pattern-inside: | + Action { + $REQ: Request[$T] => + ... + } + - pattern-inside: | + Action(...) { + $REQ: Request[$T] => + ... + } + - pattern-inside: | + Action.async { + $REQ: Request[$T] => + ... + } + - pattern-inside: | + Action.async(...) { + $REQ: Request[$T] => + ... + } + - patterns: + - pattern: $PARAM + - pattern-either: + - pattern-inside: | + def $CTRL(..., $PARAM: $TYPE, ...) = Action { + ... + } + - pattern-inside: | + def $CTRL(..., $PARAM: $TYPE, ...) = Action(...) { + ... + } + - pattern-inside: | + def $CTRL(..., $PARAM: $TYPE, ...) = Action.async { + ... + } + - pattern-inside: | + def $CTRL(..., $PARAM: $TYPE, ...) = Action.async(...) { + ... + } + pattern-sinks: + - patterns: + - pattern-either: + - pattern: $MODEL.overrideSql(...) + - pattern: sql"..." + - pattern-inside: | + import slick.$DEPS + ... + severity: ERROR + languages: + - scala +- id: scala.play.security.tainted-sql-from-http-request.tainted-sql-from-http-request + languages: [scala] + severity: ERROR + mode: taint + message: >- + User data flows into this manually-constructed SQL string. User data + can be safely inserted into SQL strings using prepared statements or an + object-relational mapper (ORM). Manually-constructed SQL strings is a + possible indicator of SQL injection, which could let an attacker steal or + manipulate data from the database. Instead, use prepared statements + (`connection.PreparedStatement`) or a safe library. + metadata: + cwe: + - "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')" + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + references: + - https://docs.oracle.com/javase/7/docs/api/java/sql/PreparedStatement.html + category: security + technology: + - scala + - play + confidence: HIGH + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: HIGH + impact: MEDIUM + pattern-sources: + - patterns: + - pattern-either: + - patterns: + - pattern: $REQ + - pattern-either: + - pattern-inside: | + Action { + $REQ: Request[$T] => + ... + } + - pattern-inside: | + Action(...) { + $REQ: Request[$T] => + ... + } + - pattern-inside: | + Action.async { + $REQ: Request[$T] => + ... + } + - pattern-inside: | + Action.async(...) { + $REQ: Request[$T] => + ... + } + - patterns: + - pattern: $PARAM + - pattern-either: + - pattern-inside: | + def $CTRL(..., $PARAM: $TYPE, ...) = Action { + ... + } + - pattern-inside: | + def $CTRL(..., $PARAM: $TYPE, ...) = Action(...) { + ... + } + - pattern-inside: | + def $CTRL(..., $PARAM: $TYPE, ...) = Action.async { + ... + } + - pattern-inside: | + def $CTRL(..., $PARAM: $TYPE, ...) = Action.async(...) { + ... + } + pattern-sinks: + - patterns: + - pattern-either: + - patterns: + - pattern-either: + - pattern: | + "$SQLSTR" + ... + - pattern: | + "$SQLSTR".format(...) + - patterns: + - pattern-inside: | + $SB = new StringBuilder("$SQLSTR"); + ... + - pattern: $SB.append(...) + - patterns: + - pattern-inside: | + $VAR = "$SQLSTR" + ... + - pattern: $VAR += ... + - metavariable-regex: + metavariable: $SQLSTR + regex: (?i)(select|delete|insert|create|update|alter|drop)\b + - patterns: + - pattern: s"..." + - pattern-regex: | + .*\b(?i)(select|delete|insert|create|update|alter|drop)\b.* + - pattern-not-inside: println(...) +- id: scala.play.security.twirl-html-var.twirl-html-var + patterns: + - pattern-either: + - pattern: | + @Html($VAL) + - pattern: | + @Html(...$VAL + ...) + - pattern: | + @Html(... + $VAL...) + - metavariable-regex: + metavariable: $VAL + regex: \w* + message: >- + Raw html content controlled by a variable detected. You may be accidentally bypassing secure methods + of rendering HTML by manually constructing HTML and this could create a cross-site scripting vulnerability, + which could + let attackers steal sensitive user data. Try to avoid using `Html()` or consider properly sanitizing + input data. + languages: [generic] + severity: WARNING + paths: + include: + - '*.html' + metadata: + category: security + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + references: + - https://www.playframework.com/documentation/2.8.x/ScalaTemplates#Escaping + technology: + - scala + - play + - twirl + confidence: LOW + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM +- id: scala.play.security.webservice-ssrf.webservice-ssrf + patterns: + - pattern: $WS.url($URL) + - pattern-either: + - pattern-inside: | + class $CLASS (..., $WS: WSClient, ...) { + ... + } + - pattern-inside: | + def $FUNC(..., $WS: WSClient, ...) = { + ... + } + - pattern-inside: | + $WS = AhcWSClient(...) + ... + - pattern-either: + - pattern-inside: | + def $FUNC(..., $URL: $T, ...) = $A { + ... + } + - pattern-inside: | + def $FUNC(..., $URL: $T, ...) = { + ... + } + message: >- + A parameter being passed directly into `WSClient` most likely lead to SSRF. + This could allow an attacker to send data to their own server, potentially exposing sensitive data + sent with this request. + They could also probe internal servers or other resources that the server running this code can access. + Do not allow arbitrary hosts. Instead, create an allowlist for approved hosts hardcode the correct + host. + metadata: + cwe: + - 'CWE-918: Server-Side Request Forgery (SSRF)' + owasp: + - A10:2021 - Server-Side Request Forgery (SSRF) + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet.html + - https://www.playframework.com/documentation/2.8.x/ScalaWS + category: security + technology: + - scala + - play + confidence: LOW + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH + languages: [scala] + severity: WARNING +- id: scala.scala-jwt.security.jwt-hardcode.scala-jwt-hardcoded-secret + languages: + - scala + message: >- + Hardcoded JWT secret or private key is used. + This is a Insufficiently Protected Credentials weakness: https://cwe.mitre.org/data/definitions/522.html + Consider using an appropriate security mechanism to protect the credentials (e.g. keeping secrets + in environment variables) + metadata: + category: security + cwe: + - 'CWE-522: Insufficiently Protected Credentials' + owasp: + - A02:2017 - Broken Authentication + - A04:2021 - Insecure Design + source-rule-url: https://semgrep.dev/blog/2020/hardcoded-secrets-unverified-tokens-and-other-common-jwt-mistakes/ + technology: + - jwt + confidence: HIGH + references: + - https://owasp.org/Top10/A04_2021-Insecure_Design + cwe2021-top25: true + subcategory: + - audit + likelihood: MEDIUM + impact: MEDIUM + pattern-either: + - pattern: | + com.auth0.jwt.algorithms.Algorithm.HMAC256("..."); + - pattern: | + $SECRET = "..."; + ... + com.auth0.jwt.algorithms.Algorithm.HMAC256($SECRET); + - pattern: | + class $CLASS { + ... + $DECL $SECRET = "..."; + ... + def $FUNC (...): $RETURNTYPE = { + ... + com.auth0.jwt.algorithms.Algorithm.HMAC256($SECRET); + ... + } + ... + } + - pattern: | + com.auth0.jwt.algorithms.Algorithm.HMAC384("..."); + - pattern: | + $SECRET = "..."; + ... + com.auth0.jwt.algorithms.Algorithm.HMAC384($SECRET); + - pattern: | + class $CLASS { + ... + $DECL $SECRET = "..."; + ... + def $FUNC (...): $RETURNTYPE = { + ... + com.auth0.jwt.algorithms.Algorithm.HMAC384($SECRET); + ... + } + ... + } + - pattern: | + com.auth0.jwt.algorithms.Algorithm.HMAC512("..."); + - pattern: | + $SECRET = "..."; + ... + com.auth0.jwt.algorithms.Algorithm.HMAC512($SECRET); + - pattern: | + class $CLASS { + ... + $DECL $SECRET = "..."; + ... + def $FUNC (...): $RETURNTYPE = { + ... + com.auth0.jwt.algorithms.Algorithm.HMAC512($SECRET); + ... + } + ... + } + severity: ERROR +- id: scala.slick.security.scala-slick-overridesql-literal.scala-slick-overridesql-literal + patterns: + - pattern: $MODEL.overrideSql($QUERY,...) + - pattern-not: $MODEL.overrideSql("...",...) + - pattern-not-inside: | + $QUERY = "..." + ... + message: >- + Detected a formatted string in a SQL statement. + This could lead to SQL injection if variables in the SQL statement are not properly sanitized. + Avoid using non literal values in `overrideSql(...)`. + languages: [scala] + severity: ERROR + metadata: + category: security + cwe: + - "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')" + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + technology: + - scala + - slick + confidence: LOW + references: + - https://owasp.org/Top10/A03_2021-Injection + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH +- id: scala.slick.security.scala-slick-sql-non-literal.scala-slick-sql-non-literal + patterns: + - pattern: sql"..." + - pattern-regex: \#\$ + - pattern-inside: | + import slick.$DEPS + ... + message: >- + Detected a formatted string in a SQL statement. This could lead to SQL + injection if variables in the SQL statement are not properly sanitized. + Avoid using `#$variable` and use `$variable` in `sql"..."` strings instead. + languages: [scala] + severity: ERROR + metadata: + source-rule-url: https://find-sec-bugs.github.io/bugs.htm#SCALA_SQL_INJECTION_SLICK + references: + - https://scala-slick.org/doc/3.3.3/sql.html#splicing-literal-values + category: security + cwe: + - "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')" + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + technology: + - scala + - slick + confidence: LOW + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH +- id: swift.lang.crypto.insecure-random.insecure-random + message: >- + A random number generator was detected which is **not** *guaranteed* to be + Cryptographically secure. If the source of entropy is used for security + purposes (e.g. with other Cryptographic operations), make sure to use the + `SecCopyRandomBytes` API explicitly. + severity: WARNING + metadata: + likelihood: LOW + impact: LOW + confidence: LOW + category: security + cwe: + - 'CWE-338: Use of Cryptographically Weak Pseudo-Random Number Generator (PRNG)' + masvs: + - 'MSTG-CRYPTO-6: All random values are generated using a sufficiently secure random number generator.' + owasp: + - A02:2021 - Cryptographic Failures + references: + - https://mobile-security.gitbook.io/masvs/security-requirements/0x08-v3-cryptography_verification_requirements + - https://developer.apple.com/documentation/security/1399291-secrandomcopybytes + - https://developer.apple.com/documentation/security/randomization_services?language=swift + - https://github.com/apple/swift-evolution/blob/main/proposals/0202-random-unification.md + subcategory: + - audit + technology: + - ios + - macos + languages: + - swift + pattern-either: + - pattern: random() + - pattern: Int.random(...) + - pattern: Bool.random(...) + - pattern: Float.random(...) + - pattern: Double.random(...) + - pattern: arc4random() + - pattern: arc4random_buf(...) + - pattern: arc4random_uniform(...) + - pattern: SystemRandomNumberGenerator(...) + - pattern: rand() +- id: swift.lang.storage.sensitive-storage-userdefaults.swift-user-defaults + message: >- + Potentially sensitive data was observed to be stored in UserDefaults, which is not adequate protection + of sensitive information. For data of a sensitive nature, applications should leverage the Keychain. + severity: WARNING + metadata: + likelihood: LOW + impact: HIGH + confidence: MEDIUM + category: security + cwe: + - 'CWE-311: Missing Encryption of Sensitive Data' + masvs: + - 'MASVS-STORAGE-1: The app securely stores sensitive data' + owasp: + - A03:2017 - Sensitive Data Exposure + - A04:2021 - Insecure Design + references: + - https://developer.apple.com/library/archive/documentation/Security/Conceptual/SecureCodingGuide/Articles/ValidatingInput.html + - https://mas.owasp.org/MASVS/controls/MASVS-STORAGE-1/ + subcategory: + - vuln + technology: + - ios + - macos + languages: + - swift + options: + symbolic_propagation: true + patterns: + - pattern-either: + - patterns: + - pattern-either: + - pattern: | + UserDefaults.standard.set("$VALUE", forKey: "$KEY") + - pattern: | + UserDefaults.standard.set("$VALUE", forKey: $KEY) + - pattern: | + UserDefaults.standard.set($VALUE, forKey: "$KEY") + - pattern: | + UserDefaults.standard.set($VALUE, forKey: $KEY) + - metavariable-regex: + metavariable: $VALUE + regex: (?i).*(passcode|password|pass_word|passphrase|pass_code|pass_word|pass_phrase)$ + - focus-metavariable: $VALUE + - patterns: + - pattern-either: + - pattern: | + UserDefaults.standard.set("$VALUE", forKey: "$KEY") + - pattern: | + UserDefaults.standard.set("$VALUE", forKey: $KEY) + - pattern: | + UserDefaults.standard.set($VALUE, forKey: "$KEY") + - pattern: | + UserDefaults.standard.set($VALUE, forKey: $KEY) + - metavariable-regex: + metavariable: $KEY + regex: (?i).*(passcode|password|pass_word|passphrase|pass_code|pass_word|pass_phrase)$ + - focus-metavariable: $KEY + - patterns: + - pattern-either: + - pattern: | + UserDefaults.standard.set("$VALUE", forKey: "$KEY") + - pattern: | + UserDefaults.standard.set("$VALUE", forKey: $KEY) + - pattern: | + UserDefaults.standard.set($VALUE, forKey: "$KEY") + - pattern: | + UserDefaults.standard.set($VALUE, forKey: $KEY) + - metavariable-regex: + metavariable: $VALUE + regex: (?i).*(api_key|apikey)$ + - focus-metavariable: $VALUE + - patterns: + - pattern-either: + - pattern: | + UserDefaults.standard.set("$VALUE", forKey: "$KEY") + - pattern: | + UserDefaults.standard.set("$VALUE", forKey: $KEY) + - pattern: | + UserDefaults.standard.set($VALUE, forKey: "$KEY") + - pattern: | + UserDefaults.standard.set($VALUE, forKey: $KEY) + - metavariable-regex: + metavariable: $KEY + regex: (?i).*(api_key|apikey)$ + - focus-metavariable: $KEY + - patterns: + - pattern-either: + - pattern: | + UserDefaults.standard.set("$VALUE", forKey: "$KEY") + - pattern: | + UserDefaults.standard.set("$VALUE", forKey: $KEY) + - pattern: | + UserDefaults.standard.set($VALUE, forKey: "$KEY") + - pattern: | + UserDefaults.standard.set($VALUE, forKey: $KEY) + - metavariable-regex: + metavariable: $VALUE + regex: (?i).*(secretkey|secret_key|secrettoken|secret_token|clientsecret|client_secret)$ + - focus-metavariable: $VALUE + - patterns: + - pattern-either: + - pattern: | + UserDefaults.standard.set("$VALUE", forKey: "$KEY") + - pattern: | + UserDefaults.standard.set("$VALUE", forKey: $KEY) + - pattern: | + UserDefaults.standard.set($VALUE, forKey: "$KEY") + - pattern: | + UserDefaults.standard.set($VALUE, forKey: $KEY) + - metavariable-regex: + metavariable: $KEY + regex: (?i).*(secretkey|secret_key|secrettoken|secret_token|clientsecret|client_secret)$ + - focus-metavariable: $KEY + - patterns: + - pattern-either: + - pattern: | + UserDefaults.standard.set("$VALUE", forKey: "$KEY") + - pattern: | + UserDefaults.standard.set("$VALUE", forKey: $KEY) + - pattern: | + UserDefaults.standard.set($VALUE, forKey: "$KEY") + - pattern: | + UserDefaults.standard.set($VALUE, forKey: $KEY) + - metavariable-regex: + metavariable: $VALUE + regex: (?i).*(cryptkey|cryptokey|crypto_key|cryptionkey|symmetrickey|privatekey|symmetric_key|private_key)$ + - focus-metavariable: $VALUE + - patterns: + - pattern-either: + - pattern: | + UserDefaults.standard.set("$VALUE", forKey: "$KEY") + - pattern: | + UserDefaults.standard.set("$VALUE", forKey: $KEY) + - pattern: | + UserDefaults.standard.set($VALUE, forKey: "$KEY") + - pattern: | + UserDefaults.standard.set($VALUE, forKey: $KEY) + - metavariable-regex: + metavariable: $KEY + regex: (?i).*(cryptkey|cryptokey|crypto_key|cryptionkey|symmetrickey|privatekey|symmetric_key|private_key)$ + - focus-metavariable: $KEY +- id: swift.sqllite.sqllite-injection-audit.swift-potential-sqlite-injection + message: >- + Potential Client-side SQL injection which has different impacts depending on the SQL use-case. The + impact may include the circumvention of local authentication mechanisms, obtaining of sensitive data + from the app, or manipulation of client-side behavior. It wasn't possible to make certain that the + source is untrusted, but the application should avoid concatenating dynamic data into SQL queries + and should instead leverage parameterized queries. + severity: WARNING + metadata: + likelihood: MEDIUM + impact: MEDIUM + confidence: LOW + category: security + cwe: + - "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')" + masvs: + - 'MASVS-CODE-4: The app validates and sanitizes all untrusted inputs.' + references: + - https://developer.apple.com/library/archive/documentation/Security/Conceptual/SecureCodingGuide/Articles/ValidatingInput.html + subcategory: + - vuln + technology: + - ios + - macos + languages: + - swift + mode: taint + pattern-sources: + - pattern-either: + - pattern: | + "...\($X)..." + - pattern: | + $SQL = "..." + $X + - pattern: | + $SQL = $X + "..." + pattern-sinks: + - patterns: + - pattern-either: + - pattern: sqlite3_exec($DB, $SQL, ...) + - pattern: sqlite3_prepare_v2($DB, $SQL, ...) + - focus-metavariable: + - $SQL +- id: swift.webview.webview-js-window.swift-webview-config-allows-js-open-windows + message: >- + Webviews were observed that explictly allow JavaScript in an WKWebview to open windows automatically. + Consider disabling this functionality if not required, following the principle of least privelege. + severity: WARNING + metadata: + likelihood: LOW + impact: LOW + confidence: HIGH + category: security + cwe: + - 'CWE-272: Least Privilege Violation' + masvs: + - 'MASVS-PLATFORM-2: The app uses WebViews securely' + references: + - https://mas.owasp.org/MASVS/controls/MASVS-PLATFORM-2/ + - https://developer.apple.com/documentation/webkit/wkpreferences/1536573-javascriptcanopenwindowsautomati + subcategory: + - audit + technology: + - ios + - macos + languages: + - swift + patterns: + - pattern: | + $P = WKPreferences() + ... + - pattern-either: + - patterns: + - pattern-inside: | + $P.JavaScriptCanOpenWindowsAutomatically = $FALSE + ... + $P.JavaScriptCanOpenWindowsAutomatically = $TRUE + # nosemgrep + - pattern-not-inside: | + ... + $P.JavaScriptCanOpenWindowsAutomatically = $TRUE + ... + $P.JavaScriptCanOpenWindowsAutomatically = $FALSE + - pattern: | + $P.JavaScriptCanOpenWindowsAutomatically = true + - metavariable-regex: + metavariable: $TRUE + regex: ^(true)$ + - metavariable-regex: + metavariable: $TRUE + regex: (.*(?!true)) + - patterns: + - pattern: | + $P.JavaScriptCanOpenWindowsAutomatically = true + # nosemgrep + - pattern-not-inside: | + ... + $P.JavaScriptCanOpenWindowsAutomatically = ... + ... + $P.JavaScriptCanOpenWindowsAutomatically = ... +- id: terraform.aws.best-practice.aws-elasticache-automatic-backup-not-enabled.aws-elasticache-automatic-backup-not-enabled + patterns: + - pattern-either: + - patterns: + - pattern: | + resource "aws_elasticache_cluster" $ANYTHING { + ... + } + - pattern-not-inside: | + resource "aws_elasticache_cluster" $ANYTHING { + ... + engine = "memcached" + ... + } + - pattern-not-inside: | + resource "aws_elasticache_cluster" $ANYTHING { + ... + snapshot_retention_limit = ... + ... + } + - patterns: + - pattern: | + resource "aws_elasticache_cluster" $ANYTHING { + ... + snapshot_retention_limit = $LIMIT + ... + } + - metavariable-comparison: + metavariable: $LIMIT + comparison: $LIMIT == 0 + message: >- + Ensure that Amazon ElastiCache clusters have automatic backup turned on. To fix this, set a `snapshot_retention_limit`. + metadata: + category: best-practice + technology: + - terraform + - aws + languages: [hcl] + severity: WARNING +- id: terraform.aws.best-practice.aws-qldb-inadequate-ledger-permissions-mode.aws-qldb-inadequate-ledger-permissions-mode + patterns: + - pattern: | + resource "aws_qldb_ledger" $ANYTHING { + ... + permissions_mode = "ALLOW_ALL" + ... + } + message: >- + The AWS QLDB ledger permissions are too permissive. Consider using "'STANDARD'" permissions mode if possible. + languages: [hcl] + severity: WARNING + metadata: + category: best-practice + technology: + - terraform + - aws +- id: terraform.aws.best-practice.aws-rds-cluster-iam-authentication-not-enabled.aws-rds-cluster-iam-authentication-not-enabled + patterns: + - pattern: | + resource "aws_rds_cluster" $ANYTHING { + ... + } + - pattern-not-inside: | + resource "aws_rds_cluster" $ANYTHING { + ... + iam_database_authentication_enabled = true + ... + } + message: >- + The AWS RDS Cluster is not configured to use IAM authentication. Consider using IAM for authentication. + languages: [hcl] + severity: WARNING + metadata: + category: best-practice + technology: + - terraform + - aws +- id: terraform.aws.best-practice.aws-rds-iam-authentication-not-enabled.aws-rds-iam-authentication-not-enabled + patterns: + - pattern: | + resource "aws_db_instance" $ANYTHING { + ... + } + - pattern-not-inside: | + resource "aws_db_instance" $ANYTHING { + ... + iam_database_authentication_enabled = true + ... + } + message: >- + The AWS RDS is not configured to use IAM authentication. Consider using IAM for authentication. + languages: [hcl] + severity: WARNING + metadata: + category: best-practice + technology: + - terraform + - aws +- id: terraform.aws.best-practice.aws-rds-multiaz-not-enabled.aws-rds-multiaz-not-enabled + patterns: + - pattern: | + resource "aws_db_instance" $ANYTHING { + ... + } + - pattern-not-inside: | + resource "aws_db_instance" $ANYTHING { + ... + multi_az = true + ... + } + message: >- + The AWS RDS is not configured to use multi-az. Consider using it if possible. + languages: [hcl] + severity: WARNING + metadata: + category: best-practice + technology: + - terraform + - aws +- id: terraform.aws.best-practice.aws-s3-bucket-versioning-not-enabled.aws-s3-bucket-versioning-not-enabled + patterns: + - pattern: | + resource "aws_s3_bucket" $ANYTHING { + ... + } + - pattern-not-inside: | + resource "aws_s3_bucket" $ANYTHING { + ... + versioning { + ... + enabled = true + ... + } + ... + } + # filter out unknowns for now + - pattern-not-inside: | + resource "aws_s3_bucket" $ANYTHING { + ... + versioning { + ... + enabled = var.$X + ... + } + ... + } + message: >- + Ensure that Amazon S3 bucket versioning is not enabled. Consider using versioning if you don't have alternative backup mechanism. + metadata: + category: best-practice + technology: + - terraform + - aws + languages: [hcl] + severity: WARNING +- id: terraform.aws.best-practice.aws-s3-object-lock-not-enabled.aws-s3-object-lock-not-enabled + patterns: + - pattern-either: + - pattern: | + resource "aws_s3_bucket" $ANYTHING { + ... + object_lock_configuration = { + object_lock_enabled = "Disabled" + } + ... + } + - pattern: | + resource "aws_s3_bucket" $ANYTHING { + ... + object_lock_configuration { + object_lock_enabled = "Disabled" + } + ... + } + message: >- + The AWS S3 object lock is not enabled. Consider using it if possible. + languages: [hcl] + severity: WARNING + metadata: + category: best-practice + technology: + - terraform + - aws +- id: terraform.aws.best-practice.missing-alb-drop-http-headers.missing-alb-drop-http-headers + severity: WARNING + languages: [hcl] + message: >- + Detected a AWS load balancer that is not configured to drop + invalid HTTP headers. Add `drop_invalid_header_fields = true` + in your resource block. + metadata: + category: best-practice + technology: + - aws + - terraform + patterns: + - pattern-either: + - pattern: | + resource "aws_lb" $ENABLED { + ... + } + - pattern: | + resource "aws_alb" $ENABLED { + ... + } + - pattern-not-inside: | + resource $ANYTHING $ENABLED { + ... + drop_invalid_header_fields = true + ... + } +- id: terraform.aws.best-practice.missing-api-gateway-cache-cluster.missing-api-gateway-cache-cluster + severity: WARNING + languages: [hcl] + message: >- + Found a AWS API Gateway Stage without cache cluster enabled. + Enabling the cache cluster feature enhances responsiveness of your API. + Add `cache_cluster_enabled = true` to your resource block. + metadata: + category: best-practice + technology: + - aws + - terraform + patterns: + - pattern: | + resource "aws_api_gateway_stage" $ANYTHING { + ... + } + - pattern-not-inside: | + resource "aws_api_gateway_stage" $ANYTHING { + ... + cache_cluster_enabled = true + ... + } +- id: terraform.aws.best-practice.missing-autoscaling-group-tags.missing-autoscaling-group-tags + patterns: + - patterns: + - patterns: + - pattern: resource "aws_autoscaling_group" $ANYTHING {...} + - pattern-not-inside: | + resource "aws_autoscaling_group" $ANYTHING { + ... + tag {...} + ... + } + - patterns: + - pattern: resource "aws_autoscaling_group" $ANYTHING {...} + - pattern-not-inside: | + resource "aws_autoscaling_group" $ANYTHING { + ... + tags = concat(...) + ... + } + message: >- # nosemgrep: yaml.semgrep.multi-line-message + There are missing tags for an AWS Auto Scaling group. Tags help track costs, allow for filtering for Auto Scaling groups, + help with access control, and aid in organizing AWS resources. Add: + `tag { + key = "key" + value = "value" + propagate_at_launch = boolean + }` + See https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/autoscaling_group for more details. + languages: [hcl] + severity: WARNING + metadata: + technology: + - aws + - terraform + category: best-practice +- id: terraform.aws.best-practice.missing-aws-autoscaling-tags.missing-aws-autoscaling-tags + patterns: + - pattern: | + resource "aws_autoscaling_group" $ANYTHING { + ... + } + - pattern-not-inside: | + resource "aws_autoscaling_group" $ANYTHING { + ... + tag { + ... + } + ... + } + - pattern-not-inside: | + resource "aws_autoscaling_group" $ANYTHING { + ... + tags = concat( + ... + ) + ... + } + message: >- + The AWS Autoscaling Group is not tagged. + languages: [hcl] + severity: WARNING + metadata: + category: best-practice + technology: + - terraform + - aws +- id: terraform.aws.best-practice.missing-aws-cross-zone-lb.missing-aws-cross-zone-lb + patterns: + - pattern-either: + - pattern: | + resource "aws_lb" $ANYTHING { + ... + load_balancer_type = ... + ... + } + - pattern: | + resource "aws_alb" $ANYTHING { + ... + load_balancer_type = ... + ... + } + - pattern-not-inside: | + resource $ANYLB $ANYTHING { + ... + enable_cross_zone_load_balancing = true + ... + } + - pattern-not-inside: | + resource $ANYLB $ANYTHING { + ... + load_balancer_type = "application" + ... + } + message: >- + The AWS cross zone load balancing is not enabled. + languages: [hcl] + severity: WARNING + metadata: + category: best-practice + technology: + - terraform + - aws +- id: terraform.aws.best-practice.missing-aws-lb-deletion-protection.missing-aws-lb-deletion-protection + patterns: + - pattern-either: + - pattern-inside: | + resource "aws_alb" "..." { + ... + } + - pattern-inside: | + resource "aws_lb" "..." { + ... + } + - pattern-not-inside: | + resource $ANYLB $ANYTHING { + ... + enable_deletion_protection = true + ... + } + message: >- + The AWS LoadBalancer deletion protection is not enabled. + languages: [hcl] + severity: WARNING + metadata: + category: best-practice + references: + - https://aws.amazon.com/what-is/load-balancing/#seo-faq-pairs#benefits-lb + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lb + technology: + - terraform + - aws +- id: terraform.aws.best-practice.missing-aws-qldb-deletion-protection.missing-aws-qldb-deletion-protection + patterns: + - pattern: | + resource "aws_qldb_ledger" $ANYTHING { + ... + deletion_protection = false + ... + } + message: >- + The AWS QLDB deletion protection is not enabled. + languages: [hcl] + severity: WARNING + metadata: + category: best-practice + technology: + - terraform + - aws +- id: terraform.aws.best-practice.missing-cloudwatch-log-group-kms-key.missing-cloudwatch-log-group-kms-key + patterns: + - patterns: + - pattern: resource "aws_cloudwatch_log_group" $ANYTHING {...} + - pattern-not-inside: | + resource "aws_cloudwatch_log_group" $ANYTHING { + ... + kms_key_id = ... + ... + } + message: >- + The AWS CloudWatch Log group is missing a KMS key. While Log group data is always encrypted, you can optionally use a KMS key instead. Add `kms_key_id = "yourKey"` to your resource block. + languages: [hcl] + severity: WARNING + metadata: + technology: + - aws + - terraform + category: best-practice +- id: terraform.aws.best-practice.missing-cloudwatch-log-group-retention.missing-cloudwatch-log-group-retention + patterns: + - patterns: + - pattern: resource "aws_cloudwatch_log_group" $ANYTHING {...} + - pattern-not-inside: | + resource "aws_cloudwatch_log_group" $ANYTHING { + ... + retention_in_days = ... + ... + } + message: >- + The AWS CloudWatch Log group is missing log retention time. By default, logs are retained indefinitely. Add `retention_in_days = ` to your resource block. + languages: [hcl] + severity: WARNING + metadata: + technology: + - aws + - terraform + category: best-practice +- id: terraform.aws.correctness.lambda-permission-logs-missing-arn-asterisk.lambda-permission-logs-missing-arn-asterisk + severity: WARNING + languages: [hcl] + message: "The `source_arn` field needs to end with an asterisk, like this: `:*` Without this, the `aws_lambda_permission` resource '$NAME' will not be created. Add the asterisk to the end of the arn. x $ARN" + metadata: + category: correctness + references: + - https://github.com/hashicorp/terraform-provider-aws/issues/14630 + technology: + - aws + - terraform + - aws-lambda + patterns: + - pattern-inside: | + resource "aws_lambda_permission" "$NAME" { ... } + - pattern: | + source_arn = $ARN + - metavariable-pattern: + metavariable: $ARN + patterns: + - pattern-regex: + arn:aws:logs.* + - pattern-not-regex: >- + arn:aws:logs:.*:\* +- id: terraform.aws.correctness.lambda-redundant-field-with-image.lambda-redundant-field-with-image + severity: WARNING + languages: [hcl] + message: 'When using the AWS Lambda "Image" package_type, `runtime` and `handler` are not necessary for Lambda to understand how to run the code. These are built into the container image. Including `runtime` or `handler` with an "Image" `package_type` will result in an error on `terraform apply`. Remove these redundant fields.' + metadata: + category: correctness + references: + - https://stackoverflow.com/questions/72771366/why-do-i-get-error-handler-and-runtime-must-be-set-when-packagetype-is-zip-whe + technology: + - aws + - terraform + - aws-lambda + patterns: + - pattern-inside: | + resource "aws_lambda_function" $NAME { + ... + package_type = "Image" + } + - pattern-either: + - pattern: handler = ... + - pattern: runtime = ... + +- id: terraform.aws.correctness.reserved-aws-lambda-environment-variable.reserved-aws-lambda-environment-variable + message: '`terraform apply` will fail because the environment variable "$VARIABLE" + is a reserved by AWS. Use another name for "$VARIABLE".' + languages: + - hcl + severity: WARNING + metadata: + category: correctness + references: + - https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html#configuration-envvars-runtime + technology: + - aws + - aws-lambda + - terraform + patterns: + - pattern-inside: | + resource "aws_lambda_function" $FUNCTION { ... } + - pattern-inside: | + environment { ... } + - pattern-inside: | + variables = { ... } + - pattern: | + $VARIABLE = ... + - metavariable-pattern: + metavariable: $VARIABLE + patterns: + - pattern-either: + - pattern: _HANDLER + - pattern: _X_AMZN_TRACE_ID + - pattern: AWS_DEFAULT_REGION + - pattern: AWS_REGION + - pattern: AWS_EXECUTION_ENV + - pattern: AWS_LAMBDA_FUNCTION_NAME + - pattern: AWS_LAMBDA_FUNCTION_MEMORY_SIZE + - pattern: AWS_LAMBDA_FUNCTION_VERSION + - pattern: AWS_LAMBDA_INITIALIZATION_TYPE + - pattern: AWS_LAMBDA_LOG_GROUP_NAME + - pattern: AWS_LAMBDA_LOG_STREAM_NAME + - pattern: AWS_ACCESS_KEY + - pattern: AWS_ACCESS_KEY_ID + - pattern: AWS_SECRET_ACCESS_KEY + - pattern: AWS_LAMBDA_RUNTIME_API + - pattern: LAMBDA_TASK_ROOT + - pattern: LAMBDA_RUNTIME_DIR +- id: terraform.aws.correctness.subscription-filter-missing-depends.subscription-filter-missing-depends + severity: WARNING + languages: [hcl] + message: 'The `aws_cloudwatch_log_subscription_filter` resource "$NAME" needs a `depends_on` clause on the `aws_lambda_permission`, otherwise Terraform may try to create these out-of-order and fail.' + metadata: + category: correctness + references: + - https://stackoverflow.com/questions/38407660/terraform-configuring-cloudwatch-log-subscription-delivery-to-lambda/38428834#38428834 + technology: + - aws + - terraform + - aws-lambda + - cloudwatch + confidence: MEDIUM + patterns: + - pattern: | + resource "aws_cloudwatch_log_subscription_filter" $NAME { + ... + destination_arn = aws_lambda_function.$LAMBDA_NAME.arn + } + - pattern-not-inside: | + resource "aws_cloudwatch_log_subscription_filter" $NAME { + ... + depends_on = [..., aws_lambda_permission.$PERMISSION_NAME, ...] + } +- id: terraform.aws.security.aws-athena-client-can-disable-workgroup-encryption.aws-athena-client-can-disable-workgroup-encryption + patterns: + - pattern: | + resource "aws_athena_workgroup" $ANYTHING { + ... + configuration { + ... + enforce_workgroup_configuration = false + ... + result_configuration { + ... + encryption_configuration { + ... + } + ... + } + ... + } + ... + } + message: The Athena workgroup configuration can be overriden by client-side settings. + The client can make changes to disable encryption settings. Enforce the configuration + to prevent client overrides. + languages: + - hcl + severity: WARNING + metadata: + category: security + technology: + - terraform + - aws + owasp: + - A03:2017 - Sensitive Data Exposure + - A04:2021 - Insecure Design + cwe: + - 'CWE-311: Missing Encryption of Sensitive Data' + references: + - https://owasp.org/Top10/A04_2021-Insecure_Design + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW +- id: terraform.aws.security.aws-athena-database-unencrypted.aws-athena-database-unencrypted + patterns: + - pattern: | + resource "aws_athena_database" $ANYTHING { + ... + } + - pattern-not-inside: | + resource "aws_athena_database" $ANYTHING { + ... + encryption_configuration { + ... + } + ... + } + message: The Athena database is unencrypted at rest. These databases are generally + derived from data in S3 buckets and should have the same level of at rest protection. + The AWS KMS encryption key protects database contents. To create your own, create + a aws_kms_key resource or use the ARN string of a key in your account. + languages: + - hcl + severity: WARNING + metadata: + category: security + technology: + - terraform + - aws + owasp: + - A03:2017 - Sensitive Data Exposure + - A04:2021 - Insecure Design + cwe: + - 'CWE-311: Missing Encryption of Sensitive Data' + references: + - https://owasp.org/Top10/A04_2021-Insecure_Design + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW +- id: terraform.aws.security.aws-athena-workgroup-unencrypted.aws-athena-workgroup-unencrypted + patterns: + - pattern: | + resource "aws_athena_workgroup" $ANYTHING { + ... + configuration { + ... + result_configuration { + ... + } + ... + } + ... + } + - pattern-not-inside: | + resource "aws_athena_workgroup" $ANYTHING { + ... + configuration { + ... + result_configuration { + ... + encryption_configuration { + ... + } + ... + } + ... + } + ... + } + message: >- + The AWS Athena Work Group is unencrypted. The AWS KMS encryption key protects backups in the work + group. To create your own, create a aws_kms_key resource or use the ARN string of a key in your account. + languages: [hcl] + severity: WARNING + metadata: + category: security + technology: + - terraform + - aws + owasp: + - A03:2017 - Sensitive Data Exposure + - A04:2021 - Insecure Design + cwe: + - 'CWE-311: Missing Encryption of Sensitive Data' + references: + - https://owasp.org/Top10/A04_2021-Insecure_Design + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW +- id: terraform.aws.security.aws-backup-vault-unencrypted.aws-backup-vault-unencrypted + patterns: + - pattern-not-inside: | + resource "aws_backup_vault" $BACKUP { + ... + kms_key_arn = ... + ... + } + - pattern: resource "aws_backup_vault" $BACKUP {...} + message: The AWS Backup vault is unencrypted. The AWS KMS encryption key protects backups in the Backup + vault. To create your own, create a aws_kms_key resource or use the ARN string of a key in your account. + languages: [hcl] + severity: WARNING + metadata: + owasp: + - A03:2017 - Sensitive Data Exposure + cwe: + - 'CWE-320: CWE CATEGORY: Key Management Errors' + technology: + - aws + - terraform + category: security + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW +- id: terraform.aws.security.aws-cloudfront-insecure-tls.aws-insecure-cloudfront-distribution-tls-version + patterns: + - pattern: | + resource "aws_cloudfront_distribution" $ANYTHING { + ... + viewer_certificate { + ... + } + ... + } + - pattern-not-inside: | + resource "aws_cloudfront_distribution" $ANYTHING { + ... + viewer_certificate { + ... + minimum_protocol_version = "TLSv1.2_2018" + ... + } + ... + } + - pattern-not-inside: | + resource "aws_cloudfront_distribution" $ANYTHING { + ... + viewer_certificate { + ... + minimum_protocol_version = "TLSv1.2_2019" + ... + } + ... + } + - pattern-not-inside: | + resource "aws_cloudfront_distribution" $ANYTHING { + ... + viewer_certificate { + ... + minimum_protocol_version = "TLSv1.2_2021" + ... + } + ... + } + message: >- + Detected an AWS CloudFront Distribution with an insecure TLS version. + TLS versions less than 1.2 are considered insecure because they + can be broken. To fix this, set your `minimum_protocol_version` to + `"TLSv1.2_2018", "TLSv1.2_2019" or "TLSv1.2_2021"`. + metadata: + category: security + technology: + - terraform + - aws + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + cwe: + - 'CWE-326: Inadequate Encryption Strength' + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + languages: [hcl] + severity: WARNING +- id: terraform.aws.security.aws-cloudtrail-encrypted-with-cmk.aws-cloudtrail-encrypted-with-cmk + patterns: + - pattern: | + resource "aws_cloudtrail" $ANYTHING { + ... + } + - pattern-not-inside: | + resource "aws_cloudtrail" $ANYTHING { + ... + kms_key_id = ... + ... + } + message: >- + Ensure CloudTrail logs are encrypted at rest using KMS CMKs. CMKs gives you control over the encryption + key in terms of access and rotation. + metadata: + category: security + technology: + - terraform + - aws + owasp: + - A03:2017 - Sensitive Data Exposure + cwe: + - 'CWE-320: CWE CATEGORY: Key Management Errors' + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.aws.security.aws-cloudwatch-log-group-no-retention.aws-cloudwatch-log-group-no-retention + patterns: + - pattern: | + resource "aws_cloudwatch_log_group" $ANYTHING { + ... + } + - pattern-not-inside: | + resource "aws_cloudwatch_log_group" $ANYTHING { + ... + retention_in_days = ... + ... + } + message: The AWS CloudWatch Log Group has no retention. Missing retention in log groups can cause losing + important event information. + languages: [hcl] + severity: WARNING + metadata: + owasp: + - A03:2017 - Sensitive Data Exposure + cwe: + - 'CWE-320: CWE CATEGORY: Key Management Errors' + technology: + - aws + - terraform + category: security + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM +- id: terraform.aws.security.aws-cloudwatch-log-group-unencrypted.aws-cloudwatch-log-group-unencrypted + patterns: + - pattern: | + resource "aws_cloudwatch_log_group" $ANYTHING { + ... + } + - pattern-not-inside: | + resource "aws_cloudwatch_log_group" $ANYTHING { + ... + kms_key_id = ... + ... + } + message: >- + By default, AWS CloudWatch Log Group is encrypted using AWS-managed keys. + However, for added security, it's recommended to configure your own AWS KMS encryption key to protect your log group in CloudWatch. + You can either create a new aws_kms_key resource or use the ARN of an existing key in your AWS account to do so. + languages: [hcl] + severity: WARNING + metadata: + owasp: + - A02:2021 - Cryptographic Failures + cwe: + - 'CWE-732: Incorrect Permission Assignment for Critical Resource' + technology: + - aws + - terraform + category: security + references: + - https://cwe.mitre.org/data/definitions/732.html + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW +- id: terraform.aws.security.aws-codebuild-artifacts-unencrypted.aws-codebuild-artifacts-unencrypted + patterns: + - pattern-inside: | + resource "aws_codebuild_project" "$ANYTHING" { + ... + } + - pattern: | + $ARTIFACTS { + ... + type = "$TYPE" + encryption_disabled = true + ... + } + - metavariable-regex: + metavariable: $ARTIFACTS + regex: ^(artifacts|secondary_artifacts)$ + - metavariable-regex: + metavariable: $TYPE + regex: ^(CODEPIPELINE|S3)$ + message: The CodeBuild project artifacts are unencrypted. All artifacts produced + by your CodeBuild project pipeline should be encrypted to prevent them from being + read if compromised. + languages: + - hcl + severity: WARNING + metadata: + category: security + technology: + - terraform + - aws + owasp: + - A03:2017 - Sensitive Data Exposure + - A04:2021 - Insecure Design + cwe: + - 'CWE-311: Missing Encryption of Sensitive Data' + references: + - https://owasp.org/Top10/A04_2021-Insecure_Design + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/codebuild_project#encryption_disabled + - https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codebuild-project-artifacts.html + - https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-codebuild-project.html + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW +- id: terraform.aws.security.aws-codebuild-project-artifacts-unencrypted.aws-codebuild-project-artifacts-unencrypted + patterns: + - pattern: | + resource "aws_codebuild_project" $ANYTHING { + ... + artifacts { + ... + encryption_disabled = true + ... + } + ... + } + - pattern-not-inside: | + resource "aws_codebuild_project" $ANYTHING { + ... + artifacts { + type = "NO_ARTIFACTS" + encryption_disabled = true + } + ... + } + - pattern-not-inside: | + resource "aws_codebuild_project" $ANYTHING { + ... + artifacts { + type = "NO_ARTIFACTS" + } + ... + } + message: The AWS CodeBuild Project Artifacts are unencrypted. The AWS KMS encryption key protects artifacts + in the CodeBuild Projects. To create your own, create a aws_kms_key resource or use the ARN string + of a key in your account. + languages: [hcl] + severity: WARNING + metadata: + owasp: + - A03:2017 - Sensitive Data Exposure + cwe: + - 'CWE-320: CWE CATEGORY: Key Management Errors' + technology: + - aws + - terraform + category: security + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW +- id: terraform.aws.security.aws-codebuild-project-unencrypted.aws-codebuild-project-unencrypted + patterns: + - pattern: | + resource "aws_codebuild_project" $ANYTHING { + ... + } + - pattern-not-inside: | + resource "aws_codebuild_project" $ANYTHING { + ... + encryption_key = ... + ... + } + message: The AWS CodeBuild Project is unencrypted. The AWS KMS encryption key protects projects in the + CodeBuild. To create your own, create a aws_kms_key resource or use the ARN string of a key in your + account. + languages: [hcl] + severity: WARNING + metadata: + owasp: + - A03:2017 - Sensitive Data Exposure + cwe: + - 'CWE-320: CWE CATEGORY: Key Management Errors' + technology: + - aws + - terraform + category: security + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - vuln + likelihood: LOW + impact: MEDIUM + confidence: MEDIUM +- id: terraform.aws.security.aws-config-aggregator-not-all-regions.aws-config-aggregator-not-all-regions + pattern-either: + - pattern: | + resource "aws_config_configuration_aggregator" $ANYTHING { + ... + account_aggregation_source { + ... + regions = ... + ... + } + ... + } + - pattern: | + resource "aws_config_configuration_aggregator" $ANYTHING { + ... + organization_aggregation_source { + ... + regions = ... + ... + } + ... + } + message: The AWS configuration aggregator does not aggregate all AWS Config region. + This may result in unmonitored configuration in regions that are thought to be + unused. Configure the aggregator with all_regions for the source. + languages: + - hcl + severity: WARNING + metadata: + category: security + technology: + - terraform + - aws + owasp: + - A09:2021 - Security Logging and Monitoring Failures + cwe: + - 'CWE-778: Insufficient Logging' + references: + - https://owasp.org/Top10/A09_2021-Security_Logging_and_Monitoring_Failures/ + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: HIGH +- id: terraform.aws.security.aws-db-instance-no-logging.aws-db-instance-no-logging + patterns: + - pattern: | + resource "aws_db_instance" $ANYTHING { + ... + } + - pattern-not-inside: | + resource "aws_db_instance" $ANYTHING { + ... + enabled_cloudwatch_logs_exports = [$SOMETHING, ...] + ... + } + message: Database instance has no logging. Missing logs can cause missing important event information. + languages: [hcl] + severity: WARNING + metadata: + owasp: + - A03:2017 - Sensitive Data Exposure + - A04:2021 - Insecure Design + cwe: + - 'CWE-311: Missing Encryption of Sensitive Data' + technology: + - aws + - terraform + category: security + references: + - https://owasp.org/Top10/A04_2021-Insecure_Design + subcategory: + - vuln + likelihood: MEDIUM + impact: LOW + confidence: MEDIUM +- id: terraform.aws.security.aws-docdb-encrypted-with-cmk.aws-docdb-encrypted-with-cmk + patterns: + - pattern: | + resource "aws_docdb_cluster" $ANYTHING { + ... + } + - pattern-not-inside: | + resource "aws_docdb_cluster" $ANYTHING { + ... + kms_key_id = ... + ... + } + message: >- + Ensure DocDB is encrypted at rest using KMS CMKs. CMKs gives you control over the encryption key in + terms of access and rotation. + metadata: + category: security + technology: + - terraform + - aws + owasp: + - A03:2017 - Sensitive Data Exposure + cwe: + - 'CWE-320: CWE CATEGORY: Key Management Errors' + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.aws.security.aws-documentdb-auditing-disabled.aws-documentdb-auditing-disabled + patterns: + - pattern: | + resource "aws_docdb_cluster" $ANYTHING { + ... + } + - pattern-not-inside: | + resource "aws_docdb_cluster" $ANYTHING { + ... + enabled_cloudwatch_logs_exports = [..., "audit", ...] + ... + } + message: >- + Auditing is not enabled for DocumentDB. To ensure that you are able to + accurately audit the usage of your DocumentDB cluster, you should enable auditing + and export logs to CloudWatch. + languages: + - hcl + severity: INFO + metadata: + category: security + technology: + - terraform + - aws + owasp: + - A09:2021 - Security Logging and Monitoring Failures + cwe: + - 'CWE-778: Insufficient Logging' + references: + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/docdb_cluster#enabled_cloudwatch_logs_exports + - https://owasp.org/Top10/A09_2021-Security_Logging_and_Monitoring_Failures/ + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: MEDIUM +- id: terraform.aws.security.aws-documentdb-storage-unencrypted.aws-documentdb-storage-unencrypted + patterns: + - pattern: | + resource "aws_docdb_cluster" $ANYTHING { + ... + } + - pattern-not-inside: | + resource "aws_docdb_cluster" $ANYTHING { + ... + storage_encrypted = true + ... + } + message: >- + The AWS DocumentDB cluster is unencrypted. The data could be read if the + underlying disks are compromised. You should enable storage encryption. + languages: + - hcl + severity: WARNING + metadata: + category: security + technology: + - terraform + - aws + owasp: + - A03:2017 - Sensitive Data Exposure + - A04:2021 - Insecure Design + cwe: + - 'CWE-311: Missing Encryption of Sensitive Data' + references: + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/docdb_cluster#storage_encrypted + - https://owasp.org/Top10/A04_2021-Insecure_Design + subcategory: + - audit + likelihood: LOW + impact: HIGH + confidence: LOW +- id: terraform.aws.security.aws-dynamodb-point-in-time-recovery-disabled.aws-dynamodb-point-in-time-recovery-disabled + patterns: + - pattern: | + resource "aws_dynamodb_table" $ANYTHING { + ... + } + - pattern-not-inside: | + resource "aws_dynamodb_table" $ANYTHING { + ... + point_in_time_recovery { + ... + enabled = true + ... + } + ... + } + message: >- + Point-in-time recovery is not enabled for the DynamoDB table. DynamoDB + tables should be protected against accidental or malicious write/delete actions. + By enabling point-in-time-recovery you can restore to a known point in the event + of loss of data. + languages: + - hcl + severity: INFO + metadata: + category: security + technology: + - terraform + - aws + cwe: + - 'CWE-221: Information Loss or Omission' + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + references: + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/dynamodb_table#point_in_time_recovery + owasp: + - A09:2021 – Security Logging and Monitoring Failures +- id: terraform.aws.security.aws-dynamodb-table-unencrypted.aws-dynamodb-table-unencrypted + patterns: + - pattern: | + resource "aws_dynamodb_table" $ANYTHING { + ... + } + - pattern-not-inside: | + resource "aws_dynamodb_table" $ANYTHING { + ... + server_side_encryption { + enabled = true + kms_key_arn = ... + } + ... + } + message: >- + By default, AWS DynamoDB Table is encrypted using AWS-managed keys. + However, for added security, it's recommended to configure your own AWS KMS encryption key to protect your data in the DynamoDB table. + You can either create a new aws_kms_key resource or use the ARN of an existing key in your AWS account to do so. + languages: [hcl] + severity: WARNING + metadata: + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + cwe: + - 'CWE-326: Inadequate Encryption Strength' + technology: + - aws + - terraform + category: security + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM +- id: terraform.aws.security.aws-ebs-snapshot-encrypted-with-cmk.aws-ebs-snapshot-encrypted-with-cmk + patterns: + - pattern: | + resource "aws_ebs_snapshot_copy" $ANYTHING { + ... + encrypted = true + ... + } + - pattern-not-inside: | + resource "aws_ebs_snapshot_copy" $ANYTHING { + ... + encrypted = true + kms_key_id = ... + ... + } + message: >- + Ensure EBS Snapshot is encrypted at rest using KMS CMKs. CMKs gives you control over the encryption + key in terms of access and rotation. + metadata: + category: security + technology: + - terraform + - aws + owasp: + - A03:2017 - Sensitive Data Exposure + cwe: + - 'CWE-320: CWE CATEGORY: Key Management Errors' + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + languages: [hcl] + severity: WARNING +- id: terraform.aws.security.aws-ebs-unencrypted.aws-ebs-unencrypted + patterns: + - pattern: | + resource "aws_ebs_encryption_by_default" $ANYTHING { + ... + enabled = false + ... + } + message: The AWS EBS is unencrypted. The AWS EBS encryption protects data in the EBS. + languages: [hcl] + severity: WARNING + metadata: + owasp: + - A03:2017 - Sensitive Data Exposure + cwe: + - 'CWE-320: CWE CATEGORY: Key Management Errors' + technology: + - aws + - terraform + category: security + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM +- id: terraform.aws.security.aws-ebs-volume-encrypted-with-cmk.aws-ebs-volume-encrypted-with-cmk + patterns: + - pattern: | + resource "aws_ebs_volume" $ANYTHING { + ... + encrypted = true + ... + } + - pattern-not-inside: | + resource "aws_ebs_volume" $ANYTHING { + ... + encrypted = true + kms_key_id = ... + ... + } + message: >- + Ensure EBS Volume is encrypted at rest using KMS CMKs. CMKs gives you control over the encryption + key in terms of access and rotation. + metadata: + category: security + technology: + - terraform + - aws + owasp: + - A03:2017 - Sensitive Data Exposure + cwe: + - 'CWE-320: CWE CATEGORY: Key Management Errors' + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.aws.security.aws-ebs-volume-unencrypted.aws-ebs-volume-unencrypted + patterns: + - pattern: | + resource "aws_ebs_volume" $ANYTHING { + ... + } + - pattern-not: | + resource "aws_ebs_volume" $ANYTHING { + ... + encrypted = true + ... + } + message: >- + The AWS EBS volume is unencrypted. The volume, the disk I/O and any derived + snapshots could be read if compromised. Volumes should be encrypted to ensure + sensitive data is stored securely. + languages: + - hcl + severity: WARNING + metadata: + category: security + technology: + - terraform + - aws + owasp: + - A03:2017 - Sensitive Data Exposure + - A04:2021 - Insecure Design + cwe: + - 'CWE-311: Missing Encryption of Sensitive Data' + references: + - https://owasp.org/Top10/A04_2021-Insecure_Design + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ebs_volume#encrypted + - https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EBSEncryption.html + subcategory: + - audit + likelihood: MEDIUM + impact: HIGH + confidence: MEDIUM +- id: terraform.aws.security.aws-ec2-has-public-ip.aws-ec2-has-public-ip + patterns: + - pattern-either: + - pattern: | + resource "aws_instance" $ANYTHING { + ... + associate_public_ip_address = true + ... + } + - pattern: | + resource "aws_launch_template" $ANYTHING { + ... + network_interfaces { + ... + associate_public_ip_address = true + ... + } + ... + } + message: >- + EC2 instances should not have a public IP address attached in order to block public access to the + instances. To fix this, set your `associate_public_ip_address` to + `"false"`. + metadata: + category: security + technology: + - terraform + - aws + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - vuln + likelihood: LOW + impact: MEDIUM + confidence: MEDIUM + languages: [hcl] + severity: WARNING +- id: terraform.aws.security.aws-ec2-launch-configuration-ebs-block-device-unencrypted.aws-ec2-launch-configuration-ebs-block-device-unencrypted + patterns: + - pattern-inside: | + resource "aws_launch_configuration" $ANYTHING { + ... + } + - pattern: | + ebs_block_device { + ... + } + - pattern-not: | + ebs_block_device { + ... + encrypted = true + ... + } + message: >- + The AWS launch configuration EBS block device is unencrypted. The block device + could be read if compromised. Block devices should be encrypted to ensure sensitive + data is held securely at rest. + languages: + - hcl + severity: WARNING + metadata: + category: security + technology: + - terraform + - aws + owasp: + - A03:2017 - Sensitive Data Exposure + - A04:2021 - Insecure Design + cwe: + - 'CWE-311: Missing Encryption of Sensitive Data' + references: + - https://owasp.org/Top10/A04_2021-Insecure_Design + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/launch_configuration#block-devices + - https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/RootDeviceStorage.html + subcategory: + - audit + likelihood: LOW + impact: HIGH + confidence: LOW + rule-origin-note: published from /src/aws-ec2-launch-configuration-block-device-unencrypted.yml + in None +- id: terraform.aws.security.aws-ec2-launch-configuration-root-block-device-unencrypted.aws-ec2-launch-configuration-root-block-device-unencrypted + patterns: + - pattern: | + resource "aws_launch_configuration" $ANYTHING { + ... + } + - pattern-not-inside: | + resource "aws_launch_configuration" $ANYTHING { + ... + root_block_device { + ... + encrypted = true + ... + } + ... + } + message: >- + The AWS launch configuration root block device is unencrypted. The block device + could be read if compromised. Block devices should be encrypted to ensure sensitive + data is held securely at rest. + languages: + - hcl + severity: WARNING + metadata: + category: security + technology: + - terraform + - aws + owasp: + - A03:2017 - Sensitive Data Exposure + - A04:2021 - Insecure Design + cwe: + - 'CWE-311: Missing Encryption of Sensitive Data' + references: + - https://owasp.org/Top10/A04_2021-Insecure_Design + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/launch_configuration#block-devices + - https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/RootDeviceStorage.html + subcategory: + - audit + likelihood: LOW + impact: HIGH + confidence: LOW + rule-origin-note: published from /src/aws-ec2-launch-configuration-block-device-unencrypted.yml + in None +- id: terraform.aws.security.aws-ec2-launch-template-metadata-service-v1-enabled.aws-ec2-launch-template-metadata-service-v1-enabled + patterns: + - pattern: | + resource "aws_launch_template" $ANYTHING { + ... + } + - pattern-not-inside: | + resource "aws_launch_template" $ANYTHING { + ... + metadata_options { + ... + http_endpoint = "disabled" + ... + } + ... + } + - pattern-not-inside: | + resource "aws_launch_template" $ANYTHING { + ... + metadata_options { + ... + http_tokens = "required" + ... + } + ... + } + message: >- + The EC2 launch template has Instance Metadata Service Version 1 (IMDSv1) + enabled. IMDSv2 introduced session authentication tokens which improve security + when talking to IMDS. You should either disable IMDS or require the use of IMDSv2. + languages: + - hcl + severity: WARNING + metadata: + category: security + technology: + - terraform + - aws + owasp: + - A07:2021 - Identification and Authentication Failures + cwe: + - 'CWE-1390: Weak Authentication' + references: + - https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/launch_configuration#metadata_options + - https://aws.amazon.com/blogs/security/defense-in-depth-open-firewalls-reverse-proxies-ssrf-vulnerabilities-ec2-instance-metadata-service + subcategory: + - audit + likelihood: LOW + impact: HIGH + confidence: MEDIUM + +- id: terraform.aws.security.aws-ec2-security-group-allows-public-ingress.aws-ec2-security-group-allows-public-ingress + patterns: + - pattern-either: + - pattern: | + resource "aws_security_group_rule" $ANYTHING { + ... + type = "ingress" + cidr_blocks = [..., "$PUBLIC_IPV4_CIDR", ...] + ... + } + - pattern: | + resource "aws_vpc_security_group_ingress_rule" $ANYTHING { + ... + cidr_ipv4 = "$PUBLIC_IPV4_CIDR" + ... + } + - patterns: + - pattern-inside: | + resource "aws_security_group" $ANYTHING { + ... + } + - pattern: | + ingress { + ... + cidr_blocks = [..., "$PUBLIC_IPV4_CIDR", ...] + ... + } + - metavariable-pattern: + metavariable: $PUBLIC_IPV4_CIDR + language: generic + # Exclude any CIDR range that starts and ends in the designated private ranges: + # - 127.0.0.0/8 (IPv4 loopback) i.e. 127.0.0.0 - 127.255.255.255 + # - 10.0.0.0/8 (IPv4 private network) i.e. 10.0.0.0 - 10.255.255.255 + # - 172.16.0.0/12 (IPv4 private network) i.e. 172.16.0.0 - 172.31.255.255 + # - 192.168.0.0/16 (IPv4 private network) i.e. 192.168.0.0 - 192.168.255.255 + # - 169.254.0.0/16 (IPv4 link-local) i.e. 169.254.0.0 - 169.254.255.255 + # - 100.64.0.0/10 (IPv4 shared address space) i.e. 100.64.0.0 - 100.127.255.255 + patterns: + # 127.0.0.0 with netmask 8-32 + - pattern-not-regex: ^127\.\d{1,3}\.\d{1,3}\.\d{1,3}/(8|9|[1-3][0-9])$ + + # 10.0.0.0 with netmask 8-32 + - pattern-not-regex: ^10\.\d{1,3}\.\d{1,3}\.\d{1,3}/(8|9|[1-3][0-9])$ + + # 172.16.0.0-172.31.0.0 with netmask 12-32 + - pattern-not-regex: ^172\.(1[6-9]|2[0-9]|3[01])\.\d{1,3}\.\d{1,3}/(1[2-9]|[23][0-9])$ + + # 192.168.0.0 with netmask 16-32 + - pattern-not-regex: ^192\.168\.\d{1,3}\.\d{1,3}/(1[6-9]|[23][0-9])$ + + # 169.254.0.0 with netmask 16-32 + - pattern-not-regex: ^169\.254\.\d{1,3}\.\d{1,3}/(1[6-9]|[23][0-9])$ + + # 100.64.0.0-100.127.0.0 with netmask 10-32 + - pattern-not-regex: ^100\.(6[4-9]|[7-9][0-9]|1[01][0-9]|12[0-7])\.\d{1,3}\.\d{1,3}/[1-3][0-9]$ + + # *Also* exclude any CIDR range containing only 1 IP address, even if it is public + - pattern-not-regex: ^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/32$ + message: >- + The security group rule allows ingress from public internet. Opening up + ports to the public internet is potentially dangerous. You should restrict access + to IP addresses or ranges that explicitly require it where possible. Set a more + restrictive CIDR range. + languages: + - hcl + severity: WARNING + metadata: + category: security + technology: + - terraform + - aws + owasp: + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule#cidr_blocks + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_security_group_ingress_rule#cidr_ipv4 + - https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/security-group-rules-reference.html + subcategory: + - audit + likelihood: MEDIUM + impact: MEDIUM + confidence: LOW +- id: terraform.aws.security.aws-ec2-security-group-rule-missing-description.aws-ec2-security-group-rule-missing-description + patterns: + - pattern-either: + - patterns: + - pattern-either: + - patterns: + - pattern-inside: | + resource "aws_security_group" $ANYTHING { + ... + $INGRESS { + ... + description = $DESCR + ... + } + ... + } + - metavariable-regex: + metavariable: $INGRESS + regex: ^(ingress|egress)$ + - patterns: + - pattern-inside: | + resource "$SECGROUP" $ANYTHING { + ... + description = $DESCR + ... + } + - metavariable-regex: + metavariable: $SECGROUP + regex: ^(aws_security_group_rule|aws_security_group)$ + - metavariable-regex: + metavariable: $DESCR + regex: ^(['\"]['\"]|['\"]Managed by Terraform['\"])$ + - focus-metavariable: $DESCR + - patterns: + - metavariable-regex: + metavariable: $INGRESS + regex: ^(ingress|egress)$ + - pattern: | + resource "aws_security_group" $ANYTHING { + ... + $INGRESS { + ... + } + ... + } + - pattern-not: | + resource "aws_security_group" $ANYTHING { + ... + $INGRESS { + ... + description = ... + ... + } + ... + } + - patterns: + - metavariable-regex: + metavariable: $SECGROUP + regex: ^(aws_security_group_rule|aws_security_group)$ + - pattern: | + resource "$SECGROUP" $ANYTHING { + ... + } + - pattern-not: | + resource "$SECGROUP" $ANYTHING { + ... + description = ... + ... + } + message: >- + The AWS security group rule is missing a description, or its + description is empty or the default value. + Security groups rules should include a meaningful + description in order to simplify auditing, debugging, and managing + security groups. + languages: + - hcl + severity: INFO + metadata: + category: security + technology: + - terraform + - aws + owasp: + - A09:2021 - Security Logging and Monitoring Failures + cwe: + - "CWE-223: Omission of Security-relevant Information" + references: + - https://shisho.dev/dojo/providers/aws/Amazon_EC2/aws-security-group/#:~:text=Ensure%20to%20keep%20the%20description%20of%20your%20security%20group%20up%2Dto%2Ddate + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group#description + - https://owasp.org/Top10/A09_2021-Security_Logging_and_Monitoring_Failures/ + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW +- id: terraform.aws.security.aws-ecr-image-scanning-disabled.aws-ecr-image-scanning-disabled + patterns: + - pattern: | + resource "aws_ecr_repository" $ANYTHING { + ... + } + - pattern-not-inside: | + resource "aws_ecr_repository" $ANYTHING { + ... + image_scanning_configuration { + ... + scan_on_push = true + ... + } + ... + } + message: >- + The ECR repository has image scans disabled. Repository image scans should + be enabled to ensure vulnerable software can be discovered and remediated as soon + as possible. + languages: + - hcl + severity: WARNING + metadata: + references: + - https://docs.aws.amazon.com/AmazonECR/latest/userguide/image-scanning.html + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecr_repository#image_scanning_configuration + - https://owasp.org/Top10/A09_2021-Security_Logging_and_Monitoring_Failures/ + category: security + technology: + - terraform + - aws + owasp: + - A09:2021 - Security Logging and Monitoring Failures + cwe: + - 'CWE-223: Omission of Security-relevant Information' + subcategory: + - audit + likelihood: MEDIUM + impact: MEDIUM + confidence: LOW +- id: terraform.aws.security.aws-ecr-mutable-image-tags.aws-ecr-mutable-image-tags + patterns: + - pattern: | + resource "aws_ecr_repository" $ANYTHING { + ... + } + - pattern-not-inside: | + resource "aws_ecr_repository" $ANYTHING { + ... + image_tag_mutability = "IMMUTABLE" + ... + } + message: >- + The ECR repository allows tag mutability. Image tags could be overwritten + with compromised images. ECR images should be set to IMMUTABLE to prevent code + injection through image mutation. This can be done by setting `image_tag_mutability` + to IMMUTABLE. + languages: + - hcl + severity: WARNING + metadata: + category: security + technology: + - terraform + - aws + owasp: + - A08:2021 - Software and Data Integrity Failures + cwe: + - 'CWE-345: Insufficient Verification of Data Authenticity' + references: + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecr_repository#image_tag_mutability + - https://owasp.org/Top10/A08_2021-Software_and_Data_Integrity_Failures/ + subcategory: + - audit + likelihood: LOW + impact: HIGH + confidence: MEDIUM +- id: terraform.aws.security.aws-ecr-repository-wildcard-principal.aws-ecr-repository-wildcard-principal + patterns: + - pattern-inside: | + resource "aws_ecr_repository_policy" $ANYTHING { + ... + } + - pattern-either: + - patterns: + - pattern: policy = "$JSONPOLICY" + - metavariable-pattern: + metavariable: $JSONPOLICY + language: json + patterns: + - pattern-not-inside: | + {..., "Effect": "Deny", ...} + - pattern-either: + - pattern: | + {..., "Principal": "*", ...} + - pattern: | + {..., "Principal": [..., "*", ...], ...} + - pattern: | + {..., "Principal": { "AWS": "*" }, ...} + - pattern: | + {..., "Principal": { "AWS": [..., "*", ...] }, ...} + - patterns: + - pattern-inside: policy = jsonencode(...) + - pattern-not-inside: | + {..., Effect = "Deny", ...} + - pattern-either: + - pattern: | + {..., Principal = "*", ...} + - pattern: | + {..., Principal = [..., "*", ...], ...} + - pattern: | + {..., Principal = { AWS = "*" }, ...} + - pattern: | + {..., Principal = { AWS = [..., "*", ...] }, ...} + message: >- + Detected wildcard access granted in your ECR repository policy principal. + This grants access to all users, including anonymous users (public access). Instead, + limit principals, actions and resources to what you need according to least privilege. + metadata: + category: security + technology: + - aws + - terraform + owasp: + - A05:2021 - Security Misconfiguration + cwe: + - 'CWE-732: Incorrect Permission Assignment for Critical Resource' + references: + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecr_repository_policy + - https://docs.aws.amazon.com/lambda/latest/operatorguide/wildcard-permissions-iam.html + - https://docs.aws.amazon.com/prescriptive-guidance/latest/patterns/monitor-amazon-ecr-repositories-for-wildcard-permissions-using-aws-cloudformation-and-aws-config.html + - https://cwe.mitre.org/data/definitions/732.html + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + license: Commons Clause License Condition v1.0[LGPL-2.1-only] + languages: + - hcl + severity: WARNING +- id: terraform.aws.security.aws-efs-filesystem-encrypted-with-cmk.aws-efs-filesystem-encrypted-with-cmk + patterns: + - pattern: | + resource "aws_efs_file_system" $ANYTHING { + ... + encrypted = true + ... + } + - pattern-not-inside: | + resource "aws_efs_file_system" $ANYTHING { + ... + encrypted = true + kms_key_id = ... + ... + } + message: >- + Ensure EFS filesystem is encrypted at rest using KMS CMKs. CMKs gives you control over the encryption + key in terms of access and rotation. + metadata: + category: security + technology: + - terraform + - aws + owasp: + - A03:2017 - Sensitive Data Exposure + cwe: + - 'CWE-320: CWE CATEGORY: Key Management Errors' + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - audit + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + languages: [hcl] + severity: WARNING +- id: terraform.aws.security.aws-elasticsearch-insecure-tls-version.aws-elasticsearch-insecure-tls-version + pattern: | + resource "aws_elasticsearch_domain" $ANYTHING { + ... + domain_endpoint_options { + ... + enforce_https = true + tls_security_policy = "Policy-Min-TLS-1-0-2019-07" + ... + } + ... + } + message: Detected an AWS Elasticsearch domain using an insecure version of TLS. To fix this, set "tls_security_policy" + equal to "Policy-Min-TLS-1-2-2019-07". + languages: + - terraform + severity: WARNING + metadata: + cwe: + - 'CWE-326: Inadequate Encryption Strength' + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + category: security + technology: + - aws + - terraform + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: HIGH +- id: terraform.aws.security.aws-elasticsearch-nodetonode-encryption.aws-elasticsearch-nodetonode-encryption-not-enabled + patterns: + - pattern-either: + - pattern: | + resource "aws_elasticsearch_domain" $ANYTHING { + ... + node_to_node_encryption { + ... + enabled = false + ... + } + ... + } + - pattern: | + resource "aws_elasticsearch_domain" $ANYTHING { + ... + cluster_config { + ... + instance_count = $COUNT + ... + } + } + - pattern-not-inside: | + resource "aws_elasticsearch_domain" $ANYTHING { + ... + cluster_config { + ... + instance_count = $COUNT + ... + } + node_to_node_encryption { + ... + enabled = true + ... + } + } + - metavariable-comparison: + metavariable: $COUNT + comparison: $COUNT > 1 + message: >- + Ensure all Elasticsearch has node-to-node encryption enabled. + metadata: + category: security + technology: + - terraform + - aws + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + cwe: + - 'CWE-326: Inadequate Encryption Strength' + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - vuln + likelihood: LOW + impact: MEDIUM + confidence: MEDIUM + languages: [hcl] + severity: WARNING +- id: terraform.aws.security.aws-elb-access-logs-not-enabled.aws-elb-access-logs-not-enabled + patterns: + - pattern-either: + - pattern: | + resource "aws_lb" $ANYTHING { + ... + } + - pattern: | + resource "aws_alb" $ANYTHING { + ... + } + - pattern-not-inside: | + resource $ANYLB $ANYTHING { + ... + access_logs { + ... + enabled = true + ... + } + ... + } + - pattern-not-inside: | + resource $ANYLB $ANYTHING { + ... + subnet_mapping { + ... + } + ... + } + message: ELB has no logging. Missing logs can cause missing important event information. + languages: [hcl] + severity: WARNING + metadata: + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + cwe: + - 'CWE-326: Inadequate Encryption Strength' + technology: + - aws + - terraform + category: security + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW +- id: terraform.aws.security.aws-emr-encrypted-with-cmk.aws-emr-encrypted-with-cmk + patterns: + - pattern-inside: | + resource "aws_emr_security_configuration" $ANYTHING { + ... + } + - pattern: configuration = "$STATEMENT" + - metavariable-pattern: + metavariable: $STATEMENT + language: json + patterns: + - pattern-not-inside: | + "AwsKmsKey": ... + message: >- + Ensure EMR is encrypted at rest using KMS CMKs. CMKs gives you control over the encryption key in + terms of access and rotation. + metadata: + category: security + technology: + - terraform + - aws + owasp: + - A03:2017 - Sensitive Data Exposure + cwe: + - 'CWE-320: CWE CATEGORY: Key Management Errors' + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.aws.security.aws-fsx-lustre-files-ystem.aws-fsx-lustre-filesystem-encrypted-with-cmk + patterns: + - pattern: | + resource "aws_fsx_lustre_file_system" $ANYTHING { + ... + } + - pattern-not-inside: | + resource "aws_fsx_lustre_file_system" $ANYTHING { + ... + kms_key_id = ... + ... + } + - pattern-regex: (^aws_kms_key\.(.*)) + message: >- + Ensure FSX Lustre file system is encrypted at rest using KMS CMKs. CMKs gives you control over the + encryption key in terms of access and rotation. + metadata: + category: security + technology: + - terraform + - aws + owasp: + - A01:2021 - Broken Access Control + cwe: + - 'CWE-200: Exposure of Sensitive Information to an Unauthorized Actor' + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.aws.security.aws-fsx-lustre-filesystem-encrypted-with-cmk.aws-fsx-lustre-filesystem-encrypted-with-cmk + patterns: + - pattern: | + resource "aws_fsx_lustre_file_system" $ANYTHING { + ... + } + - pattern-not-inside: | + resource "aws_fsx_lustre_file_system" $ANYTHING { + ... + kms_key_id = ... + ... + } + message: >- + Ensure FSX Lustre file system is encrypted at rest using KMS CMKs. CMKs gives you control over the + encryption key in terms of access and rotation. + metadata: + category: security + technology: + - terraform + - aws + owasp: + - A03:2017 - Sensitive Data Exposure + - A04:2021 - Insecure Design + cwe: + - 'CWE-311: Missing Encryption of Sensitive Data' + references: + - https://owasp.org/Top10/A04_2021-Insecure_Design + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.aws.security.aws-fsx-ontapfs-encrypted-with-cmk.aws-fsx-ontapfs-encrypted-with-cmk + patterns: + - pattern: | + resource "aws_fsx_ontap_file_system" $ANYTHING { + ... + } + - pattern-not-inside: | + resource "aws_fsx_ontap_file_system" $ANYTHING { + ... + kms_key_id = ... + ... + } + message: >- + Ensure FSX ONTAP file system is encrypted at rest using KMS CMKs. CMKs gives you control over the + encryption key in terms of access and rotation. + metadata: + category: security + technology: + - terraform + - aws + owasp: + - A03:2017 - Sensitive Data Exposure + cwe: + - 'CWE-320: CWE CATEGORY: Key Management Errors' + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.aws.security.aws-fsx-windows-encrypted-with-cmk.aws-fsx-windows-encrypted-with-cmk + patterns: + - pattern: | + resource "aws_fsx_windows_file_system" $ANYTHING { + ... + } + - pattern-not-inside: | + resource "aws_fsx_windows_file_system" $ANYTHING { + ... + kms_key_id = ... + ... + } + message: >- + Ensure FSX Windows file system is encrypted at rest using KMS CMKs. CMKs gives you control over the + encryption key in terms of access and rotation. + metadata: + category: security + technology: + - terraform + - aws + owasp: + - A03:2017 - Sensitive Data Exposure + cwe: + - 'CWE-320: CWE CATEGORY: Key Management Errors' + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.aws.security.aws-glacier-vault-any-principal.aws-glacier-vault-any-principal + patterns: + - pattern-inside: | + resource "aws_glacier_vault" $ANYTHING { + ... + } + - pattern: access_policy = "$STATEMENT" + - metavariable-pattern: + metavariable: $STATEMENT + language: json + patterns: + - pattern-inside: | + {..., "Effect": "Allow", ...} + - pattern-either: + - pattern: | + "Principal": "*" + - pattern: | + "Principal": {..., "AWS": "*", ...} + - pattern-inside: | + "Principal": {..., "AWS": ..., ...} + - pattern-regex: | + (^\"arn:aws:iam::\*:(.*)\"$) + message: >- + Detected wildcard access granted to Glacier Vault. This means anyone within your + AWS account ID can perform actions on Glacier resources. Instead, limit to + a specific identity in your account, like this: `arn:aws:iam:::`. + metadata: + category: security + technology: + - aws + owasp: + - A05:2021 - Security Misconfiguration + cwe: + - 'CWE-732: Incorrect Permission Assignment for Critical Resource' + references: + - https://cwe.mitre.org/data/definitions/732.html + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + languages: [hcl] + severity: ERROR +- id: terraform.aws.security.aws-iam-admin-policy-ssoadmin.aws-iam-admin-policy-ssoadmin + patterns: + - pattern-inside: | + resource "aws_ssoadmin_permission_set_inline_policy" $ANYTHING { + ... + } + - pattern: inline_policy = "$STATEMENT" + - metavariable-pattern: + metavariable: $STATEMENT + language: json + patterns: + - pattern-not-inside: | + {..., "Effect": "Deny", ...} + - pattern-either: + - pattern: | + {..., "Action": [..., "*", ...], "Resource": [..., "*", ...], ...} + - pattern: | + {..., "Action": "*", "Resource": "*", ...} + - pattern: | + {..., "Action": "*", "Resource": [...], ...} + - pattern: | + {..., "Action": [...], "Resource": "*", ...} + message: >- + Detected admin access granted in your policy. This means anyone with this policy can perform administrative + actions. Instead, limit actions and resources to what you need according to least privilege. + metadata: + category: security + technology: + - aws + owasp: + - A05:2021 - Security Misconfiguration + cwe: + - 'CWE-732: Incorrect Permission Assignment for Critical Resource' + references: + - https://cwe.mitre.org/data/definitions/732.html + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + languages: [hcl] + severity: ERROR +- id: terraform.aws.security.aws-iam-admin-policy.aws-iam-admin-policy + patterns: + - pattern-inside: | + resource "aws_iam_policy" $ANYTHING { + ... + } + - pattern: policy = "$STATEMENT" + - metavariable-pattern: + metavariable: $STATEMENT + language: json + patterns: + - pattern-not-inside: | + {..., "Effect": "Deny", ...} + - pattern-either: + - pattern: | + {..., "Action": [..., "*", ...], "Resource": [..., "*", ...], ...} + - pattern: | + {..., "Action": "*", "Resource": "*", ...} + - pattern: | + {..., "Action": "*", "Resource": [...], ...} + - pattern: | + {..., "Action": [...], "Resource": "*", ...} + message: >- + Detected admin access granted in your policy. This means anyone with this policy can perform administrative + actions. Instead, limit actions and resources to what you need according to least privilege. + metadata: + category: security + technology: + - aws + - terraform + owasp: + - A05:2021 - Security Misconfiguration + cwe: + - 'CWE-732: Incorrect Permission Assignment for Critical Resource' + references: + - https://cwe.mitre.org/data/definitions/732.html + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + languages: [hcl] + severity: ERROR +- id: terraform.aws.security.aws-imagebuilder-component-encrypted-with-cmk.aws-imagebuilder-component-encrypted-with-cmk + patterns: + - pattern: | + resource "aws_imagebuilder_component" $ANYTHING { + ... + } + - pattern-not-inside: | + resource "aws_imagebuilder_component" $ANYTHING { + ... + kms_key_id = ... + ... + } + message: >- + Ensure ImageBuilder component is encrypted at rest using KMS CMKs. CMKs gives you control over the + encryption key in terms of access and rotation. + metadata: + category: security + technology: + - terraform + - aws + owasp: + - A03:2017 - Sensitive Data Exposure + cwe: + - 'CWE-320: CWE CATEGORY: Key Management Errors' + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.aws.security.aws-insecure-api-gateway-tls-version.aws-insecure-api-gateway-tls-version + patterns: + - pattern-either: + - pattern: | + resource "aws_api_gateway_domain_name" $ANYTHING { + ... + security_policy = "..." + ... + } + - pattern: | + resource "aws_apigatewayv2_domain_name" $ANYTHING { + ... + domain_name_configuration {...} + ... + } + - pattern-not: | + resource "aws_api_gateway_domain_name" $ANYTHING { + ... + security_policy = "TLS_1_2" + ... + } + - pattern-not: | + resource "aws_apigatewayv2_domain_name" $ANYTHING { + ... + domain_name_configuration { + ... + security_policy = "TLS_1_2" + ... + } + } + message: Detected AWS API Gateway to be using an insecure version of TLS. To fix this issue make sure + to set "security_policy" equal to "TLS_1_2". + languages: + - terraform + severity: WARNING + metadata: + cwe: + - 'CWE-326: Inadequate Encryption Strength' + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + category: security + technology: + - aws + - terraform + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM +- id: terraform.aws.security.aws-insecure-redshift-ssl-configuration.aws-insecure-redshift-ssl-configuration + patterns: + - pattern: | + resource "aws_redshift_parameter_group" $ANYTHING { + ... + } + - pattern-not-inside: | + resource "aws_redshift_parameter_group" $ANYTHING { + ... + parameter { + name = "require_ssl" + value = "true" + } + ... + } + - pattern-not-inside: | + resource "aws_redshift_parameter_group" $ANYTHING { + ... + parameter { + name = "require_ssl" + value = true + } + ... + } + message: >- + Detected an AWS Redshift configuration with a SSL disabled. To fix this, set your `require_ssl` to + `"true"`. + metadata: + category: security + technology: + - terraform + - aws + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + cwe: + - 'CWE-326: Inadequate Encryption Strength' + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + languages: [hcl] + severity: WARNING +- id: terraform.aws.security.aws-kinesis-stream-encrypted-with-cmk.aws-kinesis-stream-encrypted-with-cmk + patterns: + - pattern: | + resource "aws_kinesis_stream" $ANYTHING { + ... + } + - pattern-not-inside: | + resource "aws_kinesis_stream" $ANYTHING { + ... + kms_key_id = ... + ... + } + message: >- + Ensure Kinesis stream is encrypted at rest using KMS CMKs. CMKs gives you control over the encryption + key in terms of access and rotation. + metadata: + category: security + technology: + - terraform + - aws + owasp: + - A03:2017 - Sensitive Data Exposure + cwe: + - 'CWE-320: CWE CATEGORY: Key Management Errors' + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.aws.security.aws-kinesis-stream-unencrypted.aws-kinesis-stream-unencrypted + patterns: + - pattern: | + resource "aws_kinesis_stream" $ANYTHING { + ... + } + - pattern-not: | + resource "aws_kinesis_stream" $ANYTHING { + ... + encryption_type = "KMS" + ... + } + message: >- + The AWS Kinesis stream does not encrypt data at rest. The data could be + read if the Kinesis stream storage layer is compromised. Enable Kinesis stream + server-side encryption. + languages: + - hcl + severity: WARNING + metadata: + category: security + technology: + - terraform + - aws + owasp: + - A03:2017 - Sensitive Data Exposure + - A04:2021 - Insecure Design + cwe: + - 'CWE-311: Missing Encryption of Sensitive Data' + references: + - https://owasp.org/Top10/A04_2021-Insecure_Design + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kinesis_stream#encryption_type + - https://docs.aws.amazon.com/streams/latest/dev/server-side-encryption.html + subcategory: + - audit + likelihood: LOW + impact: HIGH + confidence: MEDIUM + rule-origin-note: published from /src/aws-kinesis-stream-unencrypted.yml in None +- id: terraform.aws.security.aws-kinesis-video-stream-encrypted-with-cmk.aws-kinesis-video-stream-encrypted-with-cmk + patterns: + - pattern: | + resource "aws_kinesis_video_stream" $ANYTHING { + ... + } + - pattern-not-inside: | + resource "aws_kinesis_video_stream" $ANYTHING { + ... + kms_key_id = ... + ... + } + message: >- + Ensure Kinesis video stream is encrypted at rest using KMS CMKs. CMKs gives you control over the encryption + key in terms of access and rotation. + metadata: + category: security + technology: + - terraform + - aws + owasp: + - A03:2017 - Sensitive Data Exposure + cwe: + - 'CWE-320: CWE CATEGORY: Key Management Errors' + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.aws.security.aws-kms-key-wildcard-principal.aws-kms-key-wildcard-principal + patterns: + - pattern-inside: | + resource "aws_kms_key" $ANYTHING { + ... + } + - pattern: policy = "$STATEMENT" + - metavariable-pattern: + metavariable: $STATEMENT + language: json + patterns: + - pattern-not-inside: | + {..., "Effect": "Deny", ...} + - pattern-either: + - pattern: | + {..., "Principal": "*", "Action": "kms:*", "Resource": "*", ...} + - pattern: | + {..., "Principal": [..., "*", ...], "Action": "kms:*", "Resource": "*", ...} + - pattern: | + {..., "Principal": { "AWS": "*" }, "Action": "kms:*", "Resource": "*", ...} + - pattern: | + {..., "Principal": { "AWS": [..., "*", ...] }, "Action": "kms:*", "Resource": "*", ...} + message: >- + Detected wildcard access granted in your KMS key. This means anyone with this policy can perform administrative + actions over the keys. Instead, limit principals, actions and resources to what you need according + to least privilege. + metadata: + category: security + technology: + - aws + - terraform + owasp: + - A05:2021 - Security Misconfiguration + cwe: + - 'CWE-732: Incorrect Permission Assignment for Critical Resource' + references: + - https://cwe.mitre.org/data/definitions/732.html + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + languages: [hcl] + severity: ERROR +- id: terraform.aws.security.aws-kms-no-rotation.aws-kms-no-rotation + patterns: + - pattern-either: + - pattern: | + resource "aws_kms_key" $ANYTHING { + ... + enable_key_rotation = false + ... + } + - pattern: | + resource "aws_kms_key" $ANYTHING { + ... + customer_master_key_spec = "SYMMETRIC_DEFAULT" + enable_key_rotation = false + ... + } + - pattern: | + resource "aws_kms_key" $ANYTHING { + ... + } + - pattern-not-inside: | + resource "aws_kms_key" $ANYTHING { + ... + enable_key_rotation = true + ... + } + - pattern-not-inside: | + resource "aws_kms_key" $ANYTHING { + ... + customer_master_key_spec = "RSA_2096" + ... + } + message: The AWS KMS has no rotation. Missing rotation can cause leaked key to be used by attackers. + To fix this, set a `enable_key_rotation`. + languages: [hcl] + severity: WARNING + metadata: + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + cwe: + - 'CWE-326: Inadequate Encryption Strength' + technology: + - aws + - terraform + category: security + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM +- id: terraform.aws.security.aws-lambda-environment-credentials.aws-lambda-environment-credentials + patterns: + - pattern-inside: | + resource "$ANYTING" $ANYTHING { + ... + environment { + variables = { + ... + } + } + ... + } + - pattern-either: + - pattern-inside: | + AWS_ACCESS_KEY_ID = "$Y" + - pattern-regex: | + (?- + A hard-coded credential was detected. It is not recommended to store credentials in source-code, + as this risks secrets + being leaked and used by either an internal or external malicious adversary. It is recommended to + use environment variables to securely provide credentials or retrieve credentials from a secure + vault or HSM (Hardware Security Module). + metadata: + category: security + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + cwe: + - 'CWE-326: Inadequate Encryption Strength' + technology: + - aws + - terraform + - secrets + subcategory: + - vuln + likelihood: LOW + impact: HIGH + confidence: MEDIUM + languages: [hcl] + severity: ERROR +- id: terraform.aws.security.aws-lambda-environment-unencrypted.aws-lambda-environment-unencrypted + patterns: + - pattern-inside: | + resource "aws_lambda_function" $ANYTHING { + ... + } + - pattern-either: + - patterns: + - pattern: | + environment { ... } + - pattern-not-inside: | + resource $A $B { + ... + kms_key_arn = ... + ... + } + - patterns: + - pattern: | + kms_key_arn = ... + - pattern-not-inside: | + resource $A $B { + ... + environment { ... } + ... + } + - pattern: kms_key_arn = "" + message: >- + By default, the AWS Lambda Environment is encrypted using AWS-managed keys. + However, for added security, it's recommended to configure your own AWS KMS encryption key to protect your environment variables in Lambda. + You can either create a new aws_kms_key resource or use the ARN of an existing key in your AWS account to do so. + languages: [hcl] + severity: WARNING + metadata: + owasp: + - A03:2017 - Sensitive Data Exposure + cwe: + - 'CWE-320: CWE CATEGORY: Key Management Errors' + technology: + - aws + - terraform + category: security + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW +- id: terraform.aws.security.aws-lambda-permission-unrestricted-source-arn.aws-lambda-permission-unrestricted-source-arn + patterns: + - pattern: | + resource "aws_lambda_permission" $ANYTHING { + ... + principal = "$PRINCIPAL" + ... + } + - pattern-not: | + resource "aws_lambda_permission" $ANYTHING { + ... + source_arn = ... + ... + } + - metavariable-regex: + metavariable: $PRINCIPAL + regex: .*[.]amazonaws[.]com$ + message: The AWS Lambda permission has an AWS service principal but does not specify + a source ARN. If you grant permission to a service principal without specifying + the source, other accounts could potentially configure resources in their account + to invoke your Lambda function. Set the source_arn value to the ARN of the AWS + resource that invokes the function, eg. an S3 bucket, CloudWatch Events Rule, + API Gateway, or SNS topic. + languages: + - hcl + severity: ERROR + metadata: + category: security + technology: + - terraform + - aws + owasp: + - A05:2021 - Security Misconfiguration + cwe: + - 'CWE-732: Incorrect Permission Assignment for Critical Resource' + references: + - https://cwe.mitre.org/data/definitions/732.html + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_permission + - https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-permission.html + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: HIGH +- id: terraform.aws.security.aws-lambda-x-ray-tracing-not-active.aws-lambda-x-ray-tracing-not-active + patterns: + - pattern: | + resource "aws_lambda_function" $ANYTHING { + ... + } + - pattern-not: | + resource "aws_lambda_function" $ANYTHING { + ... + tracing_config { + ... + mode = "Active" + ... + } + ... + } + message: The AWS Lambda function does not have active X-Ray tracing enabled. X-Ray + tracing enables end-to-end debugging and analysis of all function activity. This + makes it easier to trace the flow of logs and identify bottlenecks, slow downs + and timeouts. + languages: + - hcl + severity: INFO + metadata: + category: security + technology: + - aws + - terraform + owasp: + - "A09:2021 Security Logging and Monitoring Failures" + cwe: + - 'CWE-778: Insufficient Logging' + references: + - https://cwe.mitre.org/data/definitions/778.html + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_function#mode + - https://docs.aws.amazon.com/lambda/latest/dg/services-xray.html + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: MEDIUM +- id: terraform.aws.security.aws-network-acl-allows-all-ports.aws-network-acl-allows-all-ports + patterns: + - pattern-either: + - pattern: | + resource "aws_network_acl_rule" $ANYTHING { + ... + protocol = $PROTOCOL + rule_action = "allow" + ... + } + - patterns: + - pattern-inside: | + resource "$NETWORK_ACL" $ANYTHING { + ... + } + - pattern-either: + - pattern: | + ingress { + ... + protocol = $PROTOCOL + action = "allow" + ... + } + - pattern: | + egress { + ... + protocol = $PROTOCOL + action = "allow" + ... + } + - metavariable-regex: + metavariable: $NETWORK_ACL + regex: ^(aws_network_acl|aws_default_network_acl)$ + - metavariable-regex: + metavariable: $PROTOCOL + regex: \A("all"|"-1"|-1)\Z + message: >- + Ingress and/or egress is allowed for all ports in the network ACL rule. + Ensure access to specific required ports is allowed, and nothing else. + languages: + - hcl + severity: WARNING + metadata: + category: security + technology: + - terraform + - aws + owasp: + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/network_acl + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/network_acl_rule + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/default_network_acl + - https://docs.aws.amazon.com/vpc/latest/userguide/vpc-network-acls.html + subcategory: + - audit + likelihood: MEDIUM + impact: MEDIUM + confidence: LOW +- id: terraform.aws.security.aws-network-acl-allows-public-ingress.aws-network-acl-allows-public-ingress + patterns: + - pattern-either: + - patterns: + - pattern: | + resource "aws_network_acl_rule" $ANYTHING { + ... + rule_action = "allow" + cidr_block = "$PUBLIC_IPV4_CIDR" + ... + } + - pattern-not: | + resource "aws_network_acl_rule" $ANYTHING { + ... + egress = true + ... + } + - patterns: + - pattern-inside: | + resource "$NETWORK_ACL" $ANYTHING { + ... + } + - pattern: | + ingress { + ... + action = "allow" + cidr_block = "$PUBLIC_IPV4_CIDR" + ... + } + - metavariable-regex: + metavariable: $NETWORK_ACL + regex: ^(aws_network_acl|aws_default_network_acl)$ + - metavariable-pattern: + metavariable: $PUBLIC_IPV4_CIDR + language: generic + # Exclude any CIDR range that starts and ends in the designated private ranges: + # - 127.0.0.0/8 (IPv4 loopback) i.e. 127.0.0.0 - 127.255.255.255 + # - 10.0.0.0/8 (IPv4 private network) i.e. 10.0.0.0 - 10.255.255.255 + # - 172.16.0.0/12 (IPv4 private network) i.e. 172.16.0.0 - 172.31.255.255 + # - 192.168.0.0/16 (IPv4 private network) i.e. 192.168.0.0 - 192.168.255.255 + # - 169.254.0.0/16 (IPv4 link-local) i.e. 169.254.0.0 - 169.254.255.255 + # - 100.64.0.0/10 (IPv4 shared address space) i.e. 100.64.0.0 - 100.127.255.255 + patterns: + # 127.0.0.0 with netmask 8-32 + - pattern-not-regex: ^127\.\d{1,3}\.\d{1,3}\.\d{1,3}/(8|9|[1-3][0-9])$ + # 10.0.0.0 with netmask 8-32 + - pattern-not-regex: ^10\.\d{1,3}\.\d{1,3}\.\d{1,3}/(8|9|[1-3][0-9])$ + # 172.16.0.0-172.31.0.0 with netmask 12-32 + - pattern-not-regex: ^172\.(1[6-9]|2[0-9]|3[01])\.\d{1,3}\.\d{1,3}/(1[2-9]|[23][0-9])$ + # 192.168.0.0 with netmask 16-32 + - pattern-not-regex: ^192\.168\.\d{1,3}\.\d{1,3}/(1[6-9]|[23][0-9])$ + # 169.254.0.0 with netmask 16-32 + - pattern-not-regex: ^169\.254\.\d{1,3}\.\d{1,3}/(1[6-9]|[23][0-9])$ + # 100.64.0.0-100.127.0.0 with netmask 10-32 + - pattern-not-regex: ^100\.(6[4-9]|[7-9][0-9]|1[01][0-9]|12[0-7])\.\d{1,3}\.\d{1,3}/[1-3][0-9]$ + # *Also* exclude any CIDR range containing only 1 IP address, even if it is public + - pattern-not-regex: ^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/32$ + message: >- + The network ACL rule allows ingress from public internet. Opening up ACLs + to the public internet is potentially dangerous. You should restrict access to + IP addresses or ranges that explicitly require it where possible. Set a more restrictive + CIDR range. + languages: + - hcl + severity: WARNING + metadata: + category: security + technology: + - terraform + - aws + owasp: + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/network_acl + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/network_acl_rule#cidr_block + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/default_network_acl#cidr_block + - https://docs.aws.amazon.com/vpc/latest/userguide/vpc-network-acls.html + subcategory: + - audit + likelihood: MEDIUM + impact: MEDIUM + confidence: LOW +- id: terraform.aws.security.aws-opensearchserverless-encrypted-with-cmk.aws-opensearchserverless-encrypted-with-cmk + patterns: + - pattern-inside: | + resource "aws_opensearchserverless_security_policy" $ANYTHING { + ... + type = "encryption" + ... + } + - pattern-either: + - patterns: + - pattern: policy = "$JSONPOLICY" + - metavariable-pattern: + metavariable: $JSONPOLICY + language: json + pattern: | + {..., "AWSOwnedKey":true, ... } + - patterns: + - pattern-inside: policy = jsonencode(...) + - pattern: | + {..., AWSOwnedKey = true, ...} + message: Ensure opensearch serverless is encrypted at rest using AWS KMS (Key + Management Service) CMK (Customer Managed Keys). CMKs give you control + over the encryption key in terms of access and rotation. + languages: + - terraform + severity: WARNING + metadata: + category: security + subcategory: + - vuln + cwe: + - "CWE-320: CWE CATEGORY: Key Management Errors" + confidence: LOW + likelihood: MEDIUM + impact: LOW + source_rule_url: https://docs.aws.amazon.com/opensearch-service/latest/developerguide/serverless-encryption.html#serverless-encryption-policies + references: + - https://docs.aws.amazon.com/opensearch-service/latest/developerguide/serverless-encryption.html#serverless-encryption-policies + technology: + - terraform + - aws + owasp: + - A2:2021 Cryptographic Failures + - A5:2021 Security Misconfiguration +- id: terraform.aws.security.aws-provider-static-credentials.aws-provider-static-credentials + patterns: + - pattern-inside: | + provider "aws" { + ... + secret_key = "$SECRET" + } + - focus-metavariable: $SECRET + message: >- + A hard-coded credential was detected. It is not recommended to store credentials in source-code, + as this risks secrets + being leaked and used by either an internal or external malicious adversary. It is recommended to + use environment variables to securely provide credentials or retrieve credentials from a secure + vault or HSM (Hardware Security Module). + languages: + - hcl + severity: WARNING + metadata: + technology: + - secrets + - aws + - terraform + category: security + cwe: + - 'CWE-798: Use of Hard-coded Credentials' + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html + owasp: + - A07:2021 - Identification and Authentication Failures + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM +- patterns: + - pattern-either: + - pattern: | + provisioner "remote-exec" { + ... + } + - pattern: | + provisioner "local-exec" { + ... + } + - pattern-inside: | + resource "aws_instance" "..." { + ... + } + id: aws-provisioner-exec + message: Provisioners are a tool of last resort and should be avoided where possible. Provisioner behavior cannot be mapped by Terraform as part of a plan, and execute arbitrary shell commands by design. + languages: + - terraform + severity: WARNING + metadata: + category: security + owasp: + - 'A03:2021 - Injection' + - 'A01:2017 - Injection' + cwe: + - "CWE-77: Improper Neutralization of Special Elements used in a Command ('Command Injection')" + - "CWE-94: Improper Control of Generation of Code ('Code Injection')" + subcategory: + - guardrail + confidence: HIGH + likelihood: HIGH + impact: MEDIUM + technology: + - terraform + references: + - https://developer.hashicorp.com/terraform/language/resources/provisioners/remote-exec + - https://developer.hashicorp.com/terraform/language/resources/provisioners/local-exec +- id: terraform.aws.security.aws-rds-backup-no-retention.aws-rds-backup-no-retention + patterns: + - pattern-either: + - pattern: | + resource "aws_rds_cluster" $ANYTHING { + ... + backup_retention_period = 0 + ... + } + - pattern: | + resource "aws_db_instance" $ANYTHING { + ... + backup_retention_period = 0 + ... + } + message: The AWS RDS has no retention. Missing retention can cause losing important event information. + To fix this, set a `backup_retention_period`. + languages: [hcl] + severity: WARNING + metadata: + owasp: + - A03:2017 - Sensitive Data Exposure + cwe: + - 'CWE-320: CWE CATEGORY: Key Management Errors' + technology: + - aws + - terraform + category: security + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM +- id: terraform.aws.security.aws-redshift-cluster-encrypted-with-cmk.aws-redshift-cluster-encrypted-with-cmk + patterns: + - pattern: | + resource "aws_redshift_cluster" $ANYTHING { + ... + } + - pattern-not-inside: | + resource "aws_redshift_cluster" $ANYTHING { + ... + kms_key_id = ... + ... + } + message: >- + Ensure AWS Redshift cluster is encrypted at rest using KMS CMKs. CMKs gives you control over the encryption + key in terms of access and rotation. + metadata: + category: security + technology: + - terraform + - aws + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.aws.security.aws-s3-bucket-object-encrypted-with-cmk.aws-s3-bucket-object-encrypted-with-cmk + patterns: + - pattern: | + resource "aws_s3_bucket_object" $ANYTHING { + ... + } + - pattern-not-inside: | + resource "aws_s3_bucket_object" $ANYTHING { + ... + kms_key_id = ... + ... + } + message: >- + Ensure S3 bucket object is encrypted at rest using KMS CMKs. CMKs gives you control over the encryption + key in terms of access and rotation. + metadata: + category: security + technology: + - terraform + - aws + owasp: + - A03:2017 - Sensitive Data Exposure + cwe: + - 'CWE-320: CWE CATEGORY: Key Management Errors' + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.aws.security.aws-s3-object-copy-encrypted-with-cmk.aws-s3-object-copy-encrypted-with-cmk + patterns: + - pattern: | + resource "aws_s3_object_copy" $ANYTHING { + ... + } + - pattern-not-inside: | + resource "aws_s3_object_copy" $ANYTHING { + ... + kms_key_id = ... + ... + } + message: >- + Ensure S3 object copies are encrypted at rest using KMS CMKs. CMKs gives you control over the encryption + key in terms of access and rotation. + metadata: + category: security + technology: + - terraform + - aws + owasp: + - A03:2017 - Sensitive Data Exposure + cwe: + - 'CWE-320: CWE CATEGORY: Key Management Errors' + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.aws.security.aws-sagemaker-domain-encrypted-with-cmk.aws-sagemaker-domain-encrypted-with-cmk + patterns: + - pattern: | + resource "aws_sagemaker_domain" $ANYTHING { + ... + } + - pattern-not-inside: | + resource "aws_sagemaker_domain" $ANYTHING { + ... + kms_key_id = ... + ... + } + message: >- + Ensure AWS Sagemaker domains are encrypted at rest using KMS CMKs. CMKs gives you control over the + encryption key in terms of access and rotation. + metadata: + category: security + technology: + - terraform + - aws + owasp: + - A03:2017 - Sensitive Data Exposure + cwe: + - 'CWE-320: CWE CATEGORY: Key Management Errors' + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.aws.security.aws-secretsmanager-secret-unencrypted.aws-secretsmanager-secret-unencrypted + patterns: + - pattern: | + resource "aws_secretsmanager_secret" $ANYTHING { + ... + } + - pattern-not-inside: | + resource "aws_secretsmanager_secret" $ANYTHING { + ... + kms_key_id = ... + ... + } + message: >- + By default, AWS SecretManager secrets are encrypted using AWS-managed keys. + However, for added security, it's recommended to configure your own AWS KMS encryption key to protect your secrets in the Secret Manager. + You can either create a new aws_kms_key resource or use the ARN of an existing key in your AWS account to do so. + languages: [hcl] + severity: WARNING + metadata: + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + cwe: + - 'CWE-326: Inadequate Encryption Strength' + technology: + - aws + - terraform + category: security + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW +- id: terraform.aws.security.aws-sns-topic-unencrypted.aws-sns-topic-unencrypted + patterns: + - pattern: | + resource "aws_sns_topic" $ANYTHING { + ... + } + - pattern-not-inside: | + resource "aws_sns_topic" $ANYTHING { + ... + kms_master_key_id = ... + ... + } + message: The AWS SNS topic is unencrypted. The SNS topic messages could be read + if compromised. The AWS KMS encryption key protects topic contents. To create + your own, create a aws_kms_key resource or use the ARN string of a key in your + account. + languages: + - hcl + severity: WARNING + metadata: + category: security + technology: + - terraform + - aws + owasp: + - A03:2017 - Sensitive Data Exposure + - A04:2021 - Insecure Design + cwe: + - 'CWE-311: Missing Encryption of Sensitive Data' + references: + - https://owasp.org/Top10/A04_2021-Insecure_Design + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW +- id: terraform.aws.security.aws-sqs-queue-policy-wildcard-action.aws-sqs-queue-policy-wildcard-action + patterns: + - pattern-either: + - pattern-inside: | + resource "aws_sqs_queue_policy" $ANYTHING { + ... + } + - pattern-inside: | + resource "aws_sqs_queue" $ANYTHING { + ... + } + - pattern-either: + - patterns: + - pattern: policy = "$JSONPOLICY" + - metavariable-pattern: + metavariable: $JSONPOLICY + language: json + patterns: + - pattern-not-inside: | + {..., "Effect": "Deny", ...} + - pattern-either: + - pattern: | + {..., "Action": "*", ...} + - pattern: | + {..., "Action": "sqs:*", ...} + - pattern: | + {..., "Action": [..., "*", ...], ...} + - pattern: | + {..., "Action": [..., "sqs:*", ...], ...} + - patterns: + - pattern-inside: policy = jsonencode(...) + - pattern-not-inside: | + {..., Effect = "Deny", ...} + - pattern-either: + - pattern: | + {..., Action = "*", ...} + - pattern: | + {..., Action = "sqs:*", ...} + - pattern: | + {..., Action = [..., "*", ...], ...} + - pattern: | + {..., Action = [..., "sqs:*", ...], ...} + message: >- + Wildcard used in your SQS queue policy action. SQS queue policies should + always grant least privilege - that is, only grant the permissions required to + perform a specific task. Implementing least privilege is important to reducing + security risks and reducing the effect of errors or malicious intent. + metadata: + category: security + technology: + - aws + - terraform + owasp: + - A05:2021 - Security Misconfiguration + cwe: + - 'CWE-732: Incorrect Permission Assignment for Critical Resource' + references: + - https://cwe.mitre.org/data/definitions/732.html + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sqs_queue + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sqs_queue_policy + - https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-security-best-practices.html + - https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-least-privilege-policy.html + subcategory: + - vuln + likelihood: LOW + impact: MEDIUM + confidence: LOW + languages: + - hcl + severity: INFO +- id: terraform.aws.security.aws-sqs-queue-policy-wildcard-principal.aws-sqs-queue-policy-wildcard-principal + patterns: + - pattern-either: + - pattern-inside: | + resource "aws_sqs_queue_policy" $ANYTHING { + ... + } + - pattern-inside: | + resource "aws_sqs_queue" $ANYTHING { + ... + } + - pattern-either: + - patterns: + - pattern: policy = "$JSONPOLICY" + - metavariable-pattern: + metavariable: $JSONPOLICY + language: json + patterns: + - pattern-not-inside: | + {..., "Effect": "Deny", ...} + - pattern-either: + - pattern: | + {..., "Principal": "*", ...} + - pattern: | + {..., "Principal": [..., "*", ...], ...} + - pattern: | + {..., "Principal": { "AWS": "*" }, ...} + - pattern: | + {..., "Principal": { "AWS": [..., "*", ...] }, ...} + - patterns: + - pattern-inside: policy = jsonencode(...) + - pattern-not-inside: | + {..., Effect = "Deny", ...} + - pattern-either: + - pattern: | + {..., Principal = "*", ...} + - pattern: | + {..., Principal = [..., "*", ...], ...} + - pattern: | + {..., Principal = { AWS = "*" }, ...} + - pattern: | + {..., Principal = { AWS = [..., "*", ...] }, ...} + message: >- + Wildcard used in your SQS queue policy principal. This grants access to + all users, including anonymous users (public access). Unless you explicitly require + anyone on the internet to be able to read or write to your queue, limit principals, + actions and resources to what you need according to least privilege. + metadata: + category: security + technology: + - aws + - terraform + owasp: + - A05:2021 - Security Misconfiguration + cwe: + - 'CWE-732: Incorrect Permission Assignment for Critical Resource' + references: + - https://cwe.mitre.org/data/definitions/732.html + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sqs_queue + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sqs_queue_policy + - https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-security-best-practices.html + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + rule-origin-note: published from /src/aws-sqs-queue-policy-wildcard-principal.yml + in None + languages: + - hcl + severity: ERROR +- id: terraform.aws.security.aws-sqs-queue-unencrypted.aws-sqs-queue-unencrypted + patterns: + - pattern: | + resource "aws_sqs_queue" $ANYTHING { + ... + } + - pattern-not: | + resource "aws_sqs_queue" $ANYTHING { + ... + sqs_managed_sse_enabled = true + ... + } + - pattern-not: | + resource "aws_sqs_queue" $ANYTHING { + ... + kms_master_key_id = ... + ... + } + message: >- + The AWS SQS queue contents are unencrypted. The data could be read if compromised. + Enable server-side encryption for your queue using SQS-managed encryption keys + (SSE-SQS), or using your own AWS KMS key (SSE-KMS). + languages: + - hcl + severity: WARNING + metadata: + category: security + technology: + - terraform + - aws + owasp: + - A03:2017 - Sensitive Data Exposure + - A04:2021 - Insecure Design + cwe: + - 'CWE-311: Missing Encryption of Sensitive Data' + references: + - https://owasp.org/Top10/A04_2021-Insecure_Design + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sqs_queue#server-side-encryption-sse + - https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-server-side-encryption.html + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW +- id: terraform.aws.security.aws-ssm-document-logging-issues.aws-ssm-document-logging-issues + patterns: + - pattern-either: + - patterns: + - pattern-not-inside: | + resource "aws_ssm_document" $ANYTHING { + ... + document_format = "YAML" + ... + } + - pattern: content = "$STATEMENT" + - metavariable-pattern: + metavariable: $STATEMENT + language: json + patterns: + - pattern-either: + - pattern: '"s3EncryptionEnabled": false' + - pattern: '"cloudWatchEncryptionEnabled": false' + - pattern: '{..., "cloudWatchLogGroupName": "", ..., "s3BucketName": "", ...}' + message: The AWS SSM logs are unencrypted or disabled. Please enable logs and use AWS KMS encryption + key to protect SSM logs. To create your own, create a aws_kms_key resource or use the ARN string of + a key in your account. + languages: [hcl] + severity: WARNING + metadata: + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + cwe: + - 'CWE-326: Inadequate Encryption Strength' + technology: + - aws + - terraform + category: security + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW +- id: terraform.aws.security.aws-subnet-has-public-ip-address.aws-subnet-has-public-ip-address + patterns: + - pattern-either: + - pattern: | + resource "aws_subnet" $ANYTHING { + ... + map_public_ip_on_launch = true + ... + } + - pattern: | + resource "aws_default_subnet" $ANYTHING { + ... + } + - pattern-not: | + resource "aws_default_subnet" $ANYTHING { + ... + map_public_ip_on_launch = false + ... + } + message: >- + Resources in the AWS subnet are assigned a public IP address. Resources + should not be exposed on the public internet, but should have access limited to + consumers required for the function of your application. Set `map_public_ip_on_launch` + to false so that resources are not publicly-accessible. + languages: + - hcl + severity: WARNING + metadata: + category: security + technology: + - terraform + - aws + owasp: + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/subnet#map_public_ip_on_launch + - https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-instance-addressing.html#concepts-public-addresses + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: MEDIUM +- id: terraform.aws.security.aws-timestream-database-encrypted-with-cmk.aws-timestream-database-encrypted-with-cmk + patterns: + - pattern: | + resource "aws_timestreamwrite_database" $ANYTHING { + ... + } + - pattern-not-inside: | + resource "aws_timestreamwrite_database" $ANYTHING { + ... + kms_key_id = ... + ... + } + message: >- + Ensure Timestream database is encrypted at rest using KMS CMKs. CMKs gives you control over the encryption + key in terms of access and rotation. + metadata: + category: security + technology: + - terraform + - aws + owasp: + - A03:2017 - Sensitive Data Exposure + cwe: + - 'CWE-320: CWE CATEGORY: Key Management Errors' + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.aws.security.aws-transfer-server-is-public.aws-transfer-server-is-public + patterns: + - pattern: | + resource "aws_transfer_server" $ANYTHING { + ... + } + - pattern-not-inside: | + resource "aws_transfer_server" $ANYTHING { + ... + endpoint_type = "VPC" + ... + } + message: >- + Transfer Server endpoint type should not have public or null configured in order to block public access. + To fix this, set your `endpoint_type` to + `"VPC"`. + metadata: + category: security + technology: + - terraform + - aws + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.aws.security.aws-workspaces-root-volume-unencrypted.aws-workspaces-root-volume-unencrypted + patterns: + - pattern: | + resource "aws_workspaces_workspace" $ANYTHING { + ... + } + - pattern-not-inside: | + resource "aws_workspaces_workspace" $ANYTHING { + ... + root_volume_encryption_enabled = true + ... + } + message: The AWS Workspace root volume is unencrypted. The AWS KMS encryption key protects root volume. + To create your own, create a aws_kms_key resource or use the ARN string of a key in your account. + languages: [hcl] + severity: WARNING + metadata: + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + cwe: + - 'CWE-326: Inadequate Encryption Strength' + technology: + - aws + - terraform + category: security + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW +- id: terraform.aws.security.aws-workspaces-user-volume-unencrypted.aws-workspaces-user-volume-unencrypted + patterns: + - pattern: | + resource "aws_workspaces_workspace" $ANYTHING { + ... + } + - pattern-not-inside: | + resource "aws_workspaces_workspace" $ANYTHING { + ... + user_volume_encryption_enabled = true + ... + } + message: The AWS Workspace user volume is unencrypted. The AWS KMS encryption key protects user volume. + To create your own, create a aws_kms_key resource or use the ARN string of a key in your account. + languages: [hcl] + severity: WARNING + metadata: + owasp: + - A03:2017 - Sensitive Data Exposure + cwe: + - 'CWE-320: CWE CATEGORY: Key Management Errors' + technology: + - aws + - terraform + category: security + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW +- id: terraform.aws.security.insecure-load-balancer-tls-version.insecure-load-balancer-tls-version + patterns: + - pattern-either: + - patterns: + - pattern: ssl_policy = $ANYTHING + # See: https://docs.aws.amazon.com/elasticloadbalancing/latest/application/create-https-listener.html#describe-ssl-policies + - pattern-not-regex: "ELBSecurityPolicy-TLS13-1-[23]-[0-9-]+" + - pattern-not-regex: "ELBSecurityPolicy-FS-1-2-[(Res)0-9-]+" + - patterns: + - pattern: protocol = "HTTP" + - pattern-not-inside: | + resource $ANYTHING $NAME { + ... + default_action { + ... + redirect { + ... + protocol = "HTTPS" + ... + } + ... + } + ... + } + - pattern-inside: | + resource $RESOURCE $X { + ... + } + - metavariable-pattern: + metavariable: $RESOURCE + patterns: + - pattern-either: + - pattern: | + "aws_lb_listener" + - pattern: | + "aws_alb_listener" + message: >- + Detected an AWS load balancer with an insecure TLS version. + TLS versions less than 1.2 are considered insecure because they + can be broken. To fix this, set your `ssl_policy` to + `"ELBSecurityPolicy-TLS13-1-2-2021-06"`, or include a default action + to redirect to HTTPS. + metadata: + category: security + technology: + - terraform + - aws + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + cwe: + - 'CWE-326: Inadequate Encryption Strength' + references: + - https://www.ietf.org/rfc/rfc5246.txt + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + languages: [hcl] + severity: WARNING +- id: terraform.aws.security.missing-athena-workgroup-encryption.missing-athena-workgroup-encryption + patterns: + - pattern: resource "aws_athena_workgroup" $ANYTHING {...} + - pattern-not-inside: | + resource "aws_athena_workgroup" $ANYTHING { + ... + encryption_configuration {...} + ... + } + message: >- + The AWS Athena Workgroup is unencrypted. Encryption protects query results in your workgroup. + To enable, add: `encryption_configuration { encryption_option = "SSE_KMS" kms_key_arn = + aws_kms_key.example.arn }` within `result_configuration { }` in your resource block, + where `encryption_option` is your chosen encryption method and `kms_key_arn` + is your KMS key ARN. + languages: [hcl] + severity: WARNING + metadata: + technology: + - aws + - terraform + category: security + owasp: + - A03:2017 - Sensitive Data Exposure + cwe: + - 'CWE-320: CWE CATEGORY: Key Management Errors' + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW +- id: terraform.aws.security.unrestricted-github-oidc-policy.unrestricted-github-oidc-policy + metadata: + category: security + subcategory: + - audit + likelihood: MEDIUM + impact: HIGH + confidence: MEDIUM + technology: + - terraform + - aws + owasp: + - A05:2017 - Sensitive Data Exposure + - A01:2021 - Broken Access Control + cwe: + - "CWE-284: Improper Access Control" + references: + - https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services#configuring-the-role-and-trust-policy + - https://dagrz.com/writing/aws-security/hacking-github-aws-oidc/ + message: "`$POLICY` is missing a `condition` block which scopes users of this policy to specific GitHub repositories. Without this, `$POLICY` is open to all users on GitHub. Add a `condition` block on the variable `token.actions.githubusercontent.com:sub` which scopes it to prevent this." + languages: + - hcl + severity: WARNING + match: + where: + - metavariable: $IDENTIFIER + regex: .*oidc-provider/token\.actions\.githubusercontent\.com + all: + - inside: | + data "aws_iam_policy_document" $POLICY { + ... + } + - | + statement { + ... + principals { + ... + type = "Federated" + identifiers = [..., $IDENTIFIER, ...] + } + } + - not: | + statement { + ... + condition { + ... + variable = "token.actions.githubusercontent.com:sub" + } + } +- id: terraform.aws.security.wildcard-assume-role.wildcard-assume-role + patterns: + - pattern-inside: | + resource "aws_iam_role" $NAME { + ... + } + - pattern: assume_role_policy = "$STATEMENT" + - metavariable-pattern: + metavariable: $STATEMENT + language: json + patterns: + - pattern-inside: | + {..., "Effect": "Allow", ..., "Action": "sts:AssumeRole", ...} + - pattern: | + "Principal": {..., "AWS": "*", ...} + message: >- + Detected wildcard access granted to sts:AssumeRole. This means anyone with your + AWS account ID and the name of the role can assume the role. Instead, limit to + a specific identity in your account, like this: `arn:aws:iam:::root`. + metadata: + cwe: + - 'CWE-250: Execution with Unnecessary Privileges' + category: security + technology: + - aws + references: + - https://rhinosecuritylabs.com/aws/assume-worst-aws-assume-role-enumeration/ + owasp: + - A06:2017 - Security Misconfiguration + - A05:2021 - Security Misconfiguration + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + languages: [hcl] + severity: ERROR +- id: terraform.azure.best-practice.azure-ad-used-auth-service-fabric.azure-ad-used-auth-service-fabric + message: >- + Ensures that Active Directory is used for authentication for Service Fabric + patterns: + - pattern: resource + - pattern-not-inside: | + resource "azurerm_service_fabric_cluster" "..." { + ... + azure_active_directory { + tenant_id = "..." + } + ... + } + - pattern-inside: | + resource "azurerm_service_fabric_cluster" "..." { + ... + } + metadata: + category: best-practice + technology: + - terraform + - azure + languages: [hcl] + severity: WARNING +- id: terraform.azure.best-practice.azure-aks-uses-azure-policies-addon.azure-aks-uses-azure-policies-addon + message: >- + Ensure that AKS uses Azure Policies Add-on + patterns: + - pattern: resource + - pattern-not-inside: | + resource "azurerm_kubernetes_cluster" "..." { + ... + addon_profile { + azure_policy { + enabled = true + } + } + ... + } + - pattern-inside: | + resource "azurerm_kubernetes_cluster" "..." { + ... + } + metadata: + category: best-practice + technology: + - terraform + - azure + languages: [hcl] + severity: INFO +- id: terraform.azure.best-practice.azure-appgateway-enables-waf.azure-appgateway-enables-waf + message: >- + Ensure that Application Gateway enables WAF + patterns: + - pattern: resource + - pattern-not-inside: | + resource "azurerm_application_gateway" "..." { + ... + waf_configuration { + enabled = true + } + ... + } + - pattern-inside: | + resource "azurerm_application_gateway" "..." { + ... + } + metadata: + category: best-practice + technology: + - terraform + - azure + languages: [hcl] + severity: WARNING +- id: terraform.azure.best-practice.azure-appservice-dotnet-framework-version.azure-appservice-dotnet-framework-version + message: >- + Ensure that Net Framework version is the latest, if used as a part of the web app + patterns: + - pattern: resource + - pattern-not-inside: | + resource "azurerm_app_service" "..." { + ... + site_config { + ... + dotnet_framework_version = "v6.0" + ... + } + ... + } + - pattern-inside: | + resource "azurerm_app_service" "..." { + ... + } + metadata: + category: best-practice + technology: + - terraform + - azure + languages: [hcl] + severity: INFO +- id: terraform.azure.best-practice.azure-appservice-ftps-state.azure-appservice-ftps-state + message: >- + Ensure FTP deployments are disabled + patterns: + - pattern: resource + - pattern-not-inside: | + resource "azurerm_app_service" "..." { + ... + site_config { + ftps_state = "FtpsOnly" + } + ... + } + - pattern-not-inside: | + resource "azurerm_app_service" "..." { + ... + site_config { + ftps_state = "Disabled" + } + ... + } + - pattern-inside: | + resource "azurerm_app_service" "..." { + ... + } + metadata: + category: best-practice + technology: + - terraform + - azure + languages: [hcl] + severity: WARNING +- id: terraform.azure.best-practice.azure-appservice-https-20-enabled.azure-appservice-https-20-enabled + message: >- + Ensure that HTTP Version is the latest if used to run the web app + patterns: + - pattern: resource + - pattern-not-inside: | + resource "azurerm_app_service" "..." { + ... + site_config { + http2_enabled = true + } + ... + } + - pattern-inside: | + resource "azurerm_app_service" "..." { + ... + } + metadata: + category: best-practice + technology: + - terraform + - azure + languages: [hcl] + severity: WARNING +- id: terraform.azure.best-practice.azure-appservice-java-version.azure-appservice-java-version + message: >- + Ensure that Java version is the latest, if used to run the web app + patterns: + - pattern: resource + - pattern-not-inside: | + resource "azurerm_app_service" "..." { + ... + site_config { + ... + java_version = "11" + ... + } + ... + } + - pattern-inside: | + resource "azurerm_app_service" "..." { + ... + } + metadata: + category: best-practice + technology: + - terraform + - azure + languages: [hcl] + severity: INFO +- id: terraform.azure.best-practice.azure-appservice-php-version.azure-appservice-php-version + message: >- + Ensure that PHP version is the latest, if used to run the web app + patterns: + - pattern: resource + - pattern-not-inside: | + resource "azurerm_app_service" "..." { + ... + site_config { + ... + php_version = "7.4" + ... + } + ... + } + - pattern-inside: | + resource "azurerm_app_service" "..." { + ... + } + metadata: + category: best-practice + technology: + - terraform + - azure + languages: [hcl] + severity: INFO +- id: terraform.azure.best-practice.azure-appservice-python-version.azure-appservice-python-version + message: >- + Ensure that Python version is the latest, if used to run the web app + patterns: + - pattern: resource + - pattern-not-inside: | + resource "azurerm_app_service" "..." { + ... + site_config { + ... + python_version = "3.10" + ... + } + ... + } + - pattern-inside: | + resource "azurerm_app_service" "..." { + ... + } + metadata: + category: best-practice + technology: + - terraform + - azure + languages: [hcl] + severity: INFO +- id: terraform.azure.best-practice.azure-appservice-used-azure-files.azure-appservice-used-azure-files + message: >- + Ensure that app services use Azure Files + patterns: + - pattern: resource + - pattern-not-inside: | + resource "azurerm_app_service" "..." { + ... + storage_account { + ... + type = "AzureFiles" + ... + } + ... + } + - pattern-inside: | + resource "azurerm_app_service" "..." { + ... + } + metadata: + category: best-practice + technology: + - terraform + - azure + languages: [hcl] + severity: INFO +- id: terraform.azure.best-practice.azure-defenderon-appservices.azure-defenderon-appservices + message: >- + Ensure that Azure Defender is set to On for App Service + patterns: + - pattern: resource + - pattern-not-inside: | + resource "azurerm_security_center_subscription_pricing" "..." { + ... + tier = "Standard" + resource_type = "AppServices" + ... + } + - pattern-inside: | + resource "azurerm_security_center_subscription_pricing" "..." { + ... + tier = "Free" + resource_type = "AppServices" + ... + } + metadata: + category: best-practice + technology: + - terraform + - azure + languages: [hcl] + severity: WARNING +- id: terraform.azure.best-practice.azure-defenderon-container-registry.azure-defenderon-container-registry + message: >- + Ensure that Azure Defender is set to On for Container + patterns: + - pattern: resource + - pattern-not-inside: | + resource "azurerm_security_center_subscription_pricing" "..." { + ... + tier = "Standard" + resource_type = "ContainerRegistry" + ... + } + - pattern-inside: | + resource "azurerm_security_center_subscription_pricing" "..." { + ... + tier = "Free" + resource_type = "ContainerRegistry" + ... + } + metadata: + category: best-practice + technology: + - terraform + - azure + languages: [hcl] + severity: WARNING +- id: terraform.azure.best-practice.azure-defenderon-keyvaults.azure-defenderon-keyvaults + message: >- + Ensure that Azure Defender is set to On for Key Vault + patterns: + - pattern: resource + - pattern-not-inside: | + resource "azurerm_security_center_subscription_pricing" "..." { + ... + tier = "Standard" + resource_type = "KeyVaults" + ... + } + - pattern-inside: | + resource "azurerm_security_center_subscription_pricing" "..." { + ... + tier = "Free" + resource_type = "KeyVaults" + ... + } + metadata: + category: best-practice + technology: + - terraform + - azure + languages: [hcl] + severity: WARNING +- id: terraform.azure.best-practice.azure-defenderon-kubernetes.azure-defenderon-kubernetes + message: >- + Ensure that Azure Defender is set to On for Kubernetes + patterns: + - pattern: resource + - pattern-not-inside: | + resource "azurerm_security_center_subscription_pricing" "..." { + ... + tier = "Standard" + resource_type = "KubernetesService" + ... + } + - pattern-inside: | + resource "azurerm_security_center_subscription_pricing" "..." { + ... + tier = "Free" + resource_type = "KubernetesService" + ... + } + metadata: + category: best-practice + technology: + - terraform + - azure + languages: [hcl] + severity: WARNING +- id: terraform.azure.best-practice.azure-defenderon-servers.azure-defenderon-servers + message: >- + Ensure that Azure Defender is set to On for Servers + patterns: + - pattern: resource + - pattern-not-inside: | + resource "azurerm_security_center_subscription_pricing" "..." { + ... + tier = "Standard" + resource_type = "VirtualMachines" + ... + } + - pattern-inside: | + resource "azurerm_security_center_subscription_pricing" "..." { + ... + tier = "Free" + resource_type = "VirtualMachines" + ... + } + metadata: + category: best-practice + technology: + - terraform + - azure + languages: [hcl] + severity: WARNING +- id: terraform.azure.best-practice.azure-defenderon-sqlservers-vms.azure-defenderon-sqlservers-vms + message: >- + Ensure that Azure Defender is set to On for SQL servers on machines + patterns: + - pattern: resource + - pattern-not-inside: | + resource "azurerm_security_center_subscription_pricing" "..." { + ... + tier = "Standard" + resource_type = "SqlServerVirtualMachines" + ... + } + - pattern-inside: | + resource "azurerm_security_center_subscription_pricing" "..." { + ... + tier = "Free" + resource_type = "SqlServerVirtualMachines" + ... + } + metadata: + category: best-practice + technology: + - terraform + - azure + languages: [hcl] + severity: WARNING +- id: terraform.azure.best-practice.azure-defenderon-sqlservers.azure-defenderon-sqlservers + message: >- + Ensure that Azure Defender is set to On for SQL servers + patterns: + - pattern: resource + - pattern-not-inside: | + resource "azurerm_security_center_subscription_pricing" "..." { + ... + tier = "Standard" + resource_type = "SqlServers" + ... + } + - pattern-inside: | + resource "azurerm_security_center_subscription_pricing" "..." { + ... + tier = "Free" + resource_type = "SqlServers" + ... + } + metadata: + category: best-practice + technology: + - terraform + - azure + languages: [hcl] + severity: WARNING +- id: terraform.azure.best-practice.azure-defenderon-storage.azure-defenderon-storage + message: >- + Ensure that Azure Defender is set to On for Storage + patterns: + - pattern: resource + - pattern-not-inside: | + resource "azurerm_security_center_subscription_pricing" "..." { + ... + tier = "Standard" + resource_type = "StorageAccounts" + ... + } + - pattern-inside: | + resource "azurerm_security_center_subscription_pricing" "..." { + ... + tier = "Free" + resource_type = "StorageAccounts" + ... + } + metadata: + category: best-practice + technology: + - terraform + - azure + languages: [hcl] + severity: WARNING +- id: terraform.azure.best-practice.azure-frontdoor-enables-waf.azure-frontdoor-enables-waf + message: >- + Ensure that Azure Front Door enables WAF + patterns: + - pattern: resource + - pattern-not-inside: | + resource "azurerm_frontdoor" "..." { + ... + web_application_firewall_policy_link_id = "..." + ... + } + - pattern-inside: | + resource "azurerm_frontdoor" "..." { + ... + } + metadata: + category: best-practice + technology: + - terraform + - azure + languages: [hcl] + severity: WARNING +- id: terraform.azure.best-practice.azure-frontdoor-use-wafmode.azure-frontdoor-use-wafmode + message: >- + Ensure that Azure Front Door uses WAF and configured in “Detection” or “Prevention” modes + patterns: + - pattern: resource + - pattern-inside: | + resource "azurerm_frontdoor_firewall_policy" "..." { + ... + policy_settings { + ... + enabled = false + ... + } + ... + } + metadata: + category: best-practice + technology: + - terraform + - azure + languages: [hcl] + severity: WARNING +- id: terraform.azure.best-practice.azure-functionapp-http-version-latest.azure-functionapp-http-version-latest + message: >- + Ensure that HTTP Version is the latest if used to run the Function app + patterns: + - pattern: resource + - pattern-not-inside: | + resource "azurerm_function_app" "..." { + ... + site_config { + ... + http2_enabled = true + ... + } + ... + } + - pattern-inside: | + resource "azurerm_function_app" "..." { + ... + } + metadata: + category: best-practice + technology: + - terraform + - azure + languages: [hcl] + severity: WARNING +- id: terraform.azure.best-practice.azure-functionapps-accessible-over-https.azure-functionapps-accessible-over-https + message: >- + Ensure that HTTP Version is the latest if used to run the Function app + patterns: + - pattern: resource + - pattern-not-inside: | + resource "azurerm_app_service" "..." { + ... + https_only = true + ... + } + - pattern-inside: | + resource "azurerm_app_service" "..." { + ... + } + metadata: + category: best-practice + technology: + - terraform + - azure + languages: [hcl] + severity: WARNING +- id: terraform.azure.best-practice.azure-keyvault-enables-firewall-rules-settings.azure-keyvault-enables-firewall-rules-settings + message: >- + Ensure that key vault allows firewall rules settings + patterns: + - pattern: resource + - pattern-not-inside: | + resource "azurerm_key_vault" "..." { + ... + network_acls { + ... + default_action = "Deny" + ... + } + ... + } + - pattern-inside: | + resource "azurerm_key_vault" "..." { + ... + } + metadata: + category: best-practice + technology: + - terraform + - azure + languages: [hcl] + severity: WARNING +- id: terraform.azure.best-practice.azure-keyvault-enables-purge-protection.azure-keyvault-enables-purge-protection + message: >- + Ensure that key vault enables purge protection + patterns: + - pattern: resource + - pattern-not-inside: | + resource "azurerm_key_vault" "..." { + ... + purge_protection_enabled = true + } + - pattern-inside: | + resource "azurerm_key_vault" "..." { + ... + } + metadata: + category: best-practice + technology: + - terraform + - azure + languages: [hcl] + severity: WARNING +- id: terraform.azure.best-practice.azure-keyvault-enables-soft-delete.azure-keyvault-enables-soft-delete + message: >- + Ensure that key vault enables soft delete + patterns: + - pattern: resource + - pattern-inside: | + resource "azurerm_key_vault" "..." { + ... + soft_delete_enabled = false + ... + } + metadata: + category: best-practice + technology: + - terraform + - azure + languages: [hcl] + severity: WARNING +- id: terraform.azure.best-practice.azure-keyvault-recovery-enabled.azure-keyvault-recovery-enabled + message: >- + Ensure the key vault is recoverable https://docs.bridgecrew.io/docs/ensure-the-key-vault-is-recoverable + patterns: + - pattern: | + resource "azurerm_key_vault" "..." { + ... + } + - pattern-not-inside: | + resource "azurerm_key_vault" "..." { + ... + purge_protection_enabled = true + ... + } + metadata: + category: best-practice + technology: + - terraform + - azure + references: + - https://docs.bridgecrew.io/docs/ensure-the-key-vault-is-recoverable + languages: [hcl] + severity: WARNING +- id: terraform.azure.best-practice.azure-mariadb-geo-backup-enabled.azure-mariadb-geo-backup-enabled + message: >- + Ensure that MariaDB server enables geo-redundant backups + patterns: + - pattern: resource + - pattern-not-inside: | + resource "azurerm_mariadb_server" "..." { + ... + geo_redundant_backup_enabled = true + ... + } + - pattern-inside: | + resource "azurerm_mariadb_server" "..." { + ... + } + metadata: + category: best-practice + technology: + - terraform + - azure + languages: [hcl] + severity: WARNING +- id: terraform.azure.best-practice.azure-mariadb-sslenforcement-enabled.azure-mariadb-sslenforcement-enabled + message: >- + Ensure Enforce SSL connection is set to Enabled for MariaDB servers + patterns: + - pattern: resource + - pattern-not-inside: | + resource "azurerm_mariadb_server" "..." { + ... + ssl_enforcement_enabled = true + ... + } + - pattern-inside: | + resource "azurerm_mariadb_server" "..." { + ... + } + metadata: + category: best-practice + technology: + - terraform + - azure + languages: [hcl] + severity: WARNING +- id: terraform.azure.best-practice.azure-monitor-log-profile-categories.azure-monitor-log-profile-categories + message: >- + Ensure audit profile captures all the activities + patterns: + - pattern: resource + - pattern-not-inside: | + resource "azurerm_monitor_log_profile" "..." { + ... + categories = [ + "Action", + "Delete", + "Write", + ] + ... + } + - pattern-inside: | + resource "azurerm_monitor_log_profile" "..." { + ... + } + metadata: + category: best-practice + technology: + - terraform + - azure + languages: [hcl] + severity: WARNING +- id: terraform.azure.best-practice.azure-monitor-log-profile-retention-days.azure-monitor-log-profile-retention-days + message: >- + Ensure that Activity Log Retention is set 365 days or greater + patterns: + - pattern: resource + - pattern-not-inside: | + resource "azurerm_monitor_log_profile" "..." { + ... + retention_policy { + ... + enabled = true + days = 365 + ... + } + ... + } + - pattern-not-inside: | + resource "azurerm_monitor_log_profile" "..." { + ... + retention_policy { + ... + enabled = false + days = 0 + ... + } + ... + } + - pattern-inside: | + resource "azurerm_monitor_log_profile" "..." { + ... + } + metadata: + category: best-practice + technology: + - terraform + - azure + languages: [hcl] + severity: WARNING +- id: terraform.azure.best-practice.azure-mysql-geo-backup-enabled.azure-mysql-geo-backup-enabled + message: >- + Ensure that MySQL server enables geo-redundant backups + patterns: + - pattern: resource + - pattern-inside: | + resource "azurerm_mysql_server" "..." { + ... + } + - pattern-not-inside: | + resource "azurerm_mysql_server" "..." { + ... + geo_redundant_backup_enabled = true + ... + } + metadata: + category: best-practice + technology: + - terraform + - azure + languages: [hcl] + severity: WARNING +- id: terraform.azure.best-practice.azure-mysql-server-tlsenforcement-enabled.azure-mysql-server-tlsenforcement-enabled + message: >- + Ensure Enforce SSL connection is set to Enabled for MySQL servers + patterns: + - pattern: resource + - pattern-inside: | + resource "azurerm_mysql_server" "..." { + ... + } + - pattern-not-inside: | + resource "azurerm_mysql_server" "..." { + ... + ssl_enforcement_enabled = true + ... + } + metadata: + category: best-practice + technology: + - terraform + - azure + languages: [hcl] + severity: WARNING +- id: terraform.azure.best-practice.azure-mysql-threat-detection-enabled.azure-mysql-threat-detection-enabled + message: >- + Ensure that MySQL server enables Threat detection policy + patterns: + - pattern: resource + - pattern-inside: | + resource "azurerm_mysql_server" "..." { + ... + } + - pattern-not-inside: | + resource "azurerm_mysql_server" "..." { + ... + threat_detection_policy { + ... + enabled = true + ... + } + ... + } + metadata: + category: best-practice + technology: + - terraform + - azure + languages: [hcl] + severity: WARNING +- id: terraform.azure.best-practice.azure-networkinterface-enable-ip-forwarding.azure-networkinterface-enable-ip-forwarding + message: >- + Ensure that Network Interfaces disable IP forwarding + patterns: + - pattern: resource + - pattern-inside: | + resource "azurerm_network_interface" "..." { + ... + enable_ip_forwarding = true + ... + } + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - azure + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.azure.best-practice.azure-postgresql-flexi-server-geo-backup-enabled.azure-postgresql-flexi-server-geo-backup-enabled + message: >- + Ensure that PostgreSQL Flexible server enables geo-redundant backups + patterns: + - pattern: resource + - pattern-not-inside: | + resource "azurerm_postgresql_flexible_server" "..." { + ... + geo_redundant_backup_enabled = true + ... + } + - pattern-inside: | + resource "azurerm_postgresql_flexible_server" "..." { + ... + } + metadata: + category: best-practice + technology: + - terraform + - azure + languages: [hcl] + severity: WARNING +- id: terraform.azure.best-practice.azure-postgresql-geo-backup-enabled.azure-postgresql-geo-backup-enabled + message: >- + Ensure that PostgreSQL server enables geo-redundant backups + patterns: + - pattern: resource + - pattern-not-inside: | + resource "azurerm_postgresql_server" "..." { + ... + geo_redundant_backup_enabled = true + ... + } + - pattern-inside: | + resource "azurerm_postgresql_server" "..." { + ... + } + metadata: + category: best-practice + technology: + - terraform + - azure + languages: [hcl] + severity: WARNING +- id: terraform.azure.best-practice.azure-postgresql-server-connection-throttling-enabled.azure-postgresql-server-connection-throttling-enabled + message: >- + Ensure server parameter connection_throttling is set to ON for PostgreSQL Database Server + patterns: + - pattern: resource + - pattern-inside: | + resource "azurerm_postgresql_configuration" "..." { + ... + } + - pattern-not-inside: | + resource "azurerm_postgresql_configuration" "..." { + ... + name = "connection_throttling" + value = "on" + ... + } + metadata: + category: best-practice + technology: + - terraform + - azure + languages: [hcl] + severity: WARNING +- id: terraform.azure.best-practice.azure-postgresql-server-log-checkpoint-enabled.azure-postgresql-server-log-checkpoint-enabled + message: >- + Ensure server parameter log_checkpoints is set to ON for PostgreSQL Database Server + patterns: + - pattern: resource + - pattern-inside: | + resource "azurerm_postgresql_configuration" "..." { + ... + } + - pattern-not-inside: | + resource "azurerm_postgresql_configuration" "..." { + ... + name = "log_checkpoints" + value = "on" + ... + } + metadata: + category: best-practice + technology: + - terraform + - azure + languages: [hcl] + severity: WARNING +- id: terraform.azure.best-practice.azure-postgresql-server-log-connections-enabled.azure-postgresql-server-log-connections-enabled + message: >- + Ensure server parameter log_connections is set to ON for PostgreSQL Database Server + patterns: + - pattern: resource + - pattern-inside: | + resource "azurerm_postgresql_configuration" "..." { + ... + } + - pattern-not-inside: | + resource "azurerm_postgresql_configuration" "..." { + ... + name = "log_connections" + value = "on" + ... + } + metadata: + category: best-practice + technology: + - terraform + - azure + languages: [hcl] + severity: WARNING +- id: terraform.azure.best-practice.azure-postgresql-ssl-enforcement-enabled.azure-postgresql-ssl-enforcement-enabled + message: >- + Ensure Enforce SSL connection is set to Enabled for PostgreSQL servers + patterns: + - pattern: resource + - pattern-inside: | + resource "azurerm_postgresql_server" "..." { + ... + } + - pattern-not-inside: | + resource "azurerm_postgresql_server" "..." { + ... + ssl_enforcement_enabled = true + ... + } + metadata: + category: best-practice + technology: + - terraform + - azure + languages: [hcl] + severity: WARNING +- id: terraform.azure.best-practice.azure-postgresql-threat-detection-enabled.azure-postgresql-threat-detection-enabled + message: >- + Ensure that PostgreSQL server enables Threat detection policy + patterns: + - pattern: resource + - pattern-inside: | + resource "azurerm_postgresql_server" "..." { + ... + } + - pattern-not-inside: | + resource "azurerm_postgresql_server" "..." { + ... + threat_detection_policy { + ... + enabled = true + ... + } + ... + } + metadata: + category: best-practice + technology: + - terraform + - azure + languages: [hcl] + severity: WARNING +- id: terraform.azure.best-practice.azure-secret-content-type.azure-secret-content-type + message: >- + Ensure that key vault secrets have “content_type” set + patterns: + - pattern: resource + - pattern-inside: | + resource "azurerm_key_vault_secret" "..." { + ... + } + - pattern-not-inside: | + resource "azurerm_key_vault_secret" "..." { + ... + content_type = "..." + ... + } + metadata: + category: best-practice + technology: + - terraform + - azure + languages: [hcl] + severity: WARNING +- id: terraform.azure.best-practice.azure-secret-expiration-date.azure-secret-expiration-date + message: >- + Ensure that the expiration date is set on all secrets + patterns: + - pattern: resource + - pattern-inside: | + resource "azurerm_key_vault_secret" "..." { + ... + } + - pattern-not-inside: | + resource "azurerm_key_vault_secret" "..." { + ... + expiration_date = "..." + ... + } + metadata: + category: best-practice + technology: + - terraform + - azure + languages: [hcl] + severity: WARNING +- id: terraform.azure.best-practice.azure-securitcenter-email-alert.azure-securitcenter-email-alert + message: >- + Ensure that Send email notification for high severity alerts is set to On + patterns: + - pattern: resource + - pattern-inside: | + resource "azurerm_security_center_contact" "..." { + ... + } + - pattern-not-inside: | + resource "azurerm_security_center_contact" "..." { + ... + alert_notifications = true + ... + } + metadata: + category: best-practice + technology: + - terraform + - azure + languages: [hcl] + severity: WARNING +- id: terraform.azure.best-practice.azure-securitycenter-contact-emails.azure-securitycenter-contact-emails + message: >- + Ensure that Security contact emails is set + patterns: + - pattern: resource + - pattern-inside: | + resource "azurerm_security_center_contact" "..." { + ... + } + - pattern-not-inside: | + resource "azurerm_security_center_contact" "..." { + ... + email = "..." + ... + } + metadata: + category: best-practice + technology: + - terraform + - azure + languages: [hcl] + severity: WARNING +- id: terraform.azure.best-practice.azure-securitycenter-contact-phone.azure-securitycenter-contact-phone + message: >- + Ensure that Security contact Phone number is set + patterns: + - pattern: resource + - pattern-inside: | + resource "azurerm_security_center_contact" "..." { + ... + } + - pattern-not-inside: | + resource "azurerm_security_center_contact" "..." { + ... + phone = "..." + ... + } + metadata: + category: best-practice + technology: + - terraform + - azure + languages: [hcl] + severity: WARNING +- id: terraform.azure.best-practice.azure-securitycenter-email-alert-admins.azure-securitycenter-email-alert-admins + message: >- + Ensure that Send email notification for high severity alerts is set to On + patterns: + - pattern: resource + - pattern-inside: | + resource "azurerm_security_center_contact" "..." { + ... + } + - pattern-not-inside: | + resource "azurerm_security_center_contact" "..." { + ... + alerts_to_admins = true + ... + } + metadata: + category: best-practice + technology: + - terraform + - azure + languages: [hcl] + severity: WARNING +- id: terraform.azure.best-practice.azure-securitycenter-standard-pricing.azure-securitycenter-standard-pricing + message: >- + Ensure that standard pricing tier is selected + patterns: + - pattern: resource + - pattern-inside: | + resource "azurerm_security_center_subscription_pricing" "..." { + ... + } + - pattern-not-inside: | + resource "azurerm_security_center_subscription_pricing" "..." { + ... + tier = "Standard" + ... + } + metadata: + category: best-practice + technology: + - terraform + - azure + languages: [hcl] + severity: WARNING +- id: terraform.azure.best-practice.azure-sqlserver-email-alerts-enabled.azure-sqlserver-email-alerts-enabled + message: >- + Ensure that Send Alerts To is enabled for MSSQL servers + patterns: + - pattern: resource + - pattern-inside: | + resource "azurerm_mssql_server_security_alert_policy" "..." { + ... + } + - pattern-not-inside: | + resource "azurerm_mssql_server_security_alert_policy" "..." { + ... + state = "Enabled" + email_addresses = ["...", ...] + ... + } + metadata: + category: best-practice + technology: + - terraform + - azure + languages: [hcl] + severity: WARNING +- id: terraform.azure.best-practice.azure-sqlserver-email-alerts-toadmins-enabled.azure-sqlserver-email-alerts-toadmins-enabled + message: >- + Ensure that Email service and co-administrators is Enabled for MSSQL servers + patterns: + - pattern: resource + - pattern-inside: | + resource "azurerm_mssql_server_security_alert_policy" "..." { + ... + } + - pattern-not-inside: | + resource "azurerm_mssql_server_security_alert_policy" "..." { + ... + state = "Enabled" + email_account_admins = true + ... + } + metadata: + category: best-practice + technology: + - terraform + - azure + languages: [hcl] + severity: WARNING +- id: terraform.azure.best-practice.azure-sqlserver-threat-detection-types.azure-sqlserver-threat-detection-types + message: >- + Ensure that Threat Detection types is set to All + patterns: + - pattern: resource + - pattern-inside: | + resource "azurerm_mssql_server_security_alert_policy" "..." { + ... + } + - pattern-not-inside: | + resource "azurerm_mssql_server_security_alert_policy" "..." { + ... + state = "Enabled" + disabled_alerts = [] + ... + } + metadata: + category: best-practice + technology: + - terraform + - azure + languages: [hcl] + severity: WARNING +- id: terraform.azure.best-practice.azure-storage-account-enables-secure-transfer.azure-storage-account-enables-secure-transfer + message: >- + Ensure that storage account enables secure transfer + patterns: + - pattern: resource + - pattern-inside: | + resource "azurerm_storage_account" "..." { + ... + enable_https_traffic_only = false + ... + } + metadata: + category: best-practice + technology: + - terraform + - azure + languages: [hcl] + severity: WARNING +- id: terraform.azure.best-practice.azure-synapse-workscape-enables-managed-virtual-network.azure-synapse-workscape-enables-managed-virtual-network + message: >- + Ensure that Azure Synapse workspaces enables managed virtual networks + patterns: + - pattern: resource + - pattern-inside: | + resource "azurerm_synapse_workspace" "..." { + ... + } + - pattern-not-inside: | + resource "azurerm_synapse_workspace" "..." { + ... + managed_virtual_network_enabled = true + ... + } + metadata: + category: best-practice + technology: + - terraform + - azure + languages: [hcl] + severity: WARNING +- id: terraform.azure.best-practice.azure-vmscale-sets-auto-os-image-patching-enabled.azure-vmscale-sets-auto-os-image-patching-enabled + message: >- + Ensure that automatic OS image patching is enabled for Virtual Machine Scale Sets + patterns: + - pattern: resource + - pattern-inside: | + resource "azurerm_virtual_machine_scale_set" "..." { + ... + } + - pattern-not-inside: | + resource "azurerm_virtual_machine_scale_set" "..." { + ... + automatic_os_upgrade = true + os_profile_windows_config { + ... + enable_automatic_upgrades = true + ... + } + ... + } + metadata: + category: best-practice + technology: + - terraform + - azure + languages: [hcl] + severity: WARNING +- id: terraform.azure.best-practice.azure-waf-specificed-mode-app-gw.azure-waf-specificed-mode-app-gw + message: >- + Ensure that Application Gateway uses WAF in “Detection” or “Prevention” modes + patterns: + - pattern: resource + - pattern-inside: | + resource "azurerm_web_application_firewall_policy" "..." { + ... + policy_settings { + enabled = false + } + ... + } + metadata: + category: best-practice + technology: + - terraform + - azure + languages: [hcl] + severity: WARNING +- id: terraform.azure.security.aks.azure-aks-apiserver-auth-ip-ranges.azure-aks-apiserver-auth-ip-ranges + message: >- + Ensure AKS has an API Server Authorized IP Ranges enabled + patterns: + - pattern: resource + - pattern-not-inside: | + resource "azurerm_kubernetes_cluster" "..." { + ... + api_server_authorized_ip_ranges = ["..."] + ... + } + - pattern-inside: | + resource "azurerm_kubernetes_cluster" "..." { + ... + } + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - azure + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.azure.security.aks.azure-aks-private-clusters-enabled.azure-aks-private-clusters-enabled + message: >- + Ensure that AKS enables private clusters + patterns: + - pattern: resource + - pattern-not-inside: | + resource "azurerm_kubernetes_cluster" "..." { + ... + private_cluster_enabled = true + ... + } + - pattern-inside: | + resource "azurerm_kubernetes_cluster" "..." { + ... + } + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - azure + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.azure.security.aks.azure-aks-uses-disk-encryptionset.azure-aks-uses-disk-encryptionset + message: >- + Ensure that AKS uses disk encryption set + patterns: + - pattern: resource + - pattern-not-inside: | + resource "azurerm_kubernetes_cluster" "..." { + ... + disk_encryption_set_id = "..." + ... + } + - pattern-inside: | + resource "azurerm_kubernetes_cluster" "..." { + ... + } + metadata: + owasp: + - A03:2017 - Sensitive Data Exposure + cwe: + - 'CWE-320: CWE CATEGORY: Key Management Errors' + category: security + technology: + - terraform + - azure + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.azure.security.apiservice.azure-apiservices-use-virtualnetwork.azure-apiservices-use-virtualnetwork + message: >- + Ensure that API management services use virtual networks + patterns: + - pattern: resource + - pattern-not-inside: | + resource "azurerm_api_management" "..." { + ... + virtual_network_configuration { + subnet_id = ... + } + ... + } + - pattern-inside: | + resource "azurerm_api_management" "..." { + ... + } + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - azure + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.azure.security.appservice.appservice-account-identity-registered.appservice-account-identity-registered + message: >- + Registering the identity used by an App with AD allows it to interact with other services without + using username and password. + Set the `identity` block in your appservice. + patterns: + - pattern: resource + - pattern-not-inside: | + resource "azurerm_app_service" "..." { + ... + identity { + type = "..." + identity_ids = "..." + } + ... + } + - pattern-not-inside: | + resource "azurerm_app_service" "..." { + ... + identity { + type = "SystemAssigned" + } + ... + } + - pattern-inside: | + resource "azurerm_app_service" "..." { + ... + } + metadata: + category: security + owasp: + - A02:2017 - Broken Authentication + - A07:2021 - Identification and Authentication Failures + cwe: + - 'CWE-287: Improper Authentication' + technology: + - terraform + - azure + references: + - https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/app_service#identity + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: INFO +- id: terraform.azure.security.appservice.appservice-authentication-enabled.appservice-authentication-enabled + message: >- + Enabling authentication ensures that all communications in the application are authenticated. + The `auth_settings` block needs to be filled out with the appropriate auth backend settings + patterns: + - pattern: resource + - pattern-not-inside: | + resource "azurerm_app_service" "..." { + ... + auth_settings { + ... + enabled = true + ... + } + ... + } + - pattern-either: + - pattern-inside: | + resource "azurerm_app_service" "..." { + ... + } + - pattern-inside: | + resource "azurerm_app_service" "..." { + ... + auth_settings { + ... + enabled = false + ... + } + ... + } + metadata: + cwe: + - 'CWE-287: Improper Authentication' + category: security + technology: + - terraform + - azure + references: + - https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/app_service#auth_settings + owasp: + - A02:2017 - Broken Authentication + - A07:2021 - Identification and Authentication Failures + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + languages: [hcl] + severity: ERROR +- id: terraform.azure.security.appservice.appservice-enable-http2.appservice-enable-http2 + message: >- + Use the latest version of HTTP to ensure you are benefiting from security fixes. Add `http2_enabled + = true` to your appservice + resource block + patterns: + - pattern: resource + - pattern-not-inside: | + resource "azurerm_app_service" "..." { + ... + site_config { + ... + http2_enabled = true + ... + } + ... + } + - pattern-either: + - pattern-inside: | + resource "azurerm_app_service" "..." { + ... + } + - pattern-inside: | + resource "azurerm_app_service" "..." { + ... + site_config { + ... + http2_enabled = false + ... + } + ... + } + metadata: + cwe: + - "CWE-444: Inconsistent Interpretation of HTTP Requests ('HTTP Request/Response Smuggling')" + category: security + technology: + - terraform + - azure + references: + - https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/app_service#http2_enabled + owasp: + - A04:2021 - Insecure Design + subcategory: + - vuln + likelihood: LOW + impact: MEDIUM + confidence: MEDIUM + languages: [hcl] + severity: INFO +- id: terraform.azure.security.appservice.appservice-enable-https-only.appservice-enable-https-only + message: >- + By default, clients can connect to App Service by using both HTTP or HTTPS. HTTP should be disabled + enabling the HTTPS + Only setting. + patterns: + - pattern: resource + - pattern-not-inside: | + resource "azurerm_app_service" "..." { + ... + https_only = true + ... + } + - pattern-either: + - pattern-inside: | + resource "azurerm_app_service" "..." { + ... + } + - pattern-inside: | + resource "azurerm_app_service" "..." { + ... + https_only = false + ... + } + metadata: + cwe: + - 'CWE-319: Cleartext Transmission of Sensitive Information' + category: security + technology: + - terraform + - azure + references: + - https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/app_service#https_only + - https://docs.microsoft.com/en-us/azure/app-service/configure-ssl-bindings#enforce-https + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + languages: [hcl] + severity: ERROR +- id: terraform.azure.security.appservice.appservice-require-client-cert.appservice-require-client-cert + message: >- + Detected an AppService that was not configured to use a client certificate. Add `client_cert_enabled + = true` + in your resource block. + patterns: + - pattern: resource + - pattern-not-inside: | + resource "azurerm_app_service" "..." { + ... + client_cert_enabled = true + ... + } + - pattern-either: + - pattern-inside: | + resource "azurerm_app_service" "..." { + ... + } + - pattern-inside: | + resource "azurerm_app_service" "..." { + ... + client_cert_enabled = false + ... + } + metadata: + cwe: + - 'CWE-295: Improper Certificate Validation' + category: security + technology: + - terraform + - azure + references: + - https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/app_service#client_cert_enabled + owasp: + - A03:2017 - Sensitive Data Exposure + - A07:2021 - Identification and Authentication Failures + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + languages: [hcl] + severity: INFO +- id: terraform.azure.security.appservice.appservice-use-secure-tls-policy.appservice-use-secure-tls-policy + message: >- + Detected an AppService that was not configured to use TLS 1.2. Add `site_config.min_tls_version = + "1.2"` + in your resource block. + patterns: + - pattern: min_tls_version = $ANYTHING + - pattern-inside: | + resource "azurerm_app_service" "$NAME" { + ... + } + - pattern-not-inside: min_tls_version = "1.2" + metadata: + cwe: + - 'CWE-326: Inadequate Encryption Strength' + category: security + technology: + - terraform + - azure + references: + - https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/app_service#min_tls_version + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + subcategory: + - vuln + likelihood: LOW + impact: MEDIUM + confidence: HIGH + languages: [hcl] + severity: ERROR +- id: terraform.azure.security.appservice.azure-appservice-auth.azure-appservice-auth + message: >- + Ensure App Service Authentication is set on Azure App Service + patterns: + - pattern: resource + - pattern-not-inside: | + resource "azurerm_app_service" "..." { + ... + auth_settings { + ... + enabled = true + ... + } + ... + } + - pattern-inside: | + resource "azurerm_app_service" "..." { + ... + } + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - azure + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.azure.security.appservice.azure-appservice-client-certificate.azure-appservice-client-certificate + message: >- + Ensure the web app has Client Certificates + patterns: + - pattern: resource + - pattern-not-inside: | + resource "azurerm_app_service" "..." { + ... + client_cert_enabled = true + ... + } + - pattern-inside: | + resource "azurerm_app_service" "..." { + ... + } + metadata: + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + cwe: + - 'CWE-326: Inadequate Encryption Strength' + category: security + technology: + - terraform + - azure + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.azure.security.appservice.azure-appservice-detailed-errormessages-enabled.azure-appservice-detailed-errormessages-enabled + message: >- + Ensure that App service enables detailed error messages + patterns: + - pattern: resource + - pattern-not-inside: | + resource "azurerm_app_service" "..." { + ... + logs { + ... + detailed_error_messages_enabled = true + ... + } + ... + } + - pattern-inside: | + resource "azurerm_app_service" "..." { + ... + } + metadata: + owasp: + - A10:2017 - Insufficient Logging & Monitoring + - A09:2021 - Security Logging and Monitoring Failures + cwe: + - 'CWE-778: Insufficient Logging' + category: security + technology: + - terraform + - azure + references: + - https://owasp.org/Top10/A09_2021-Security_Logging_and_Monitoring_Failures + subcategory: + - vuln + likelihood: LOW + impact: LOW + confidence: MEDIUM + languages: [hcl] + severity: WARNING +- id: terraform.azure.security.appservice.azure-appservice-disallowed-cors.azure-appservice-disallowed-cors + patterns: + - pattern: | + ["*"] + - pattern-inside: allowed_origins = ... + - pattern-inside: | + $RESOURCE "azurerm_app_service" "..." { + ... + } + message: Ensure that CORS disallows every resource to access app services + languages: [hcl] + severity: WARNING + metadata: + owasp: + - A05:2021 - Security Misconfiguration + cwe: + - 'CWE-942: Permissive Cross-domain Policy with Untrusted Domains' + category: security + technology: + - terraform + - azure + + references: + - https://owasp.org/Top10/A05_2021-Security_Misconfiguration + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW +- id: terraform.azure.security.appservice.azure-appservice-enabled-failed-request.azure-appservice-enabled-failed-request + message: >- + Ensure that App service enables failed request tracing + patterns: + - pattern: resource + - pattern-not-inside: | + resource "azurerm_app_service" "..." { + ... + logs { + ... + failed_request_tracing_enabled = true + ... + } + ... + } + - pattern-inside: | + resource "azurerm_app_service" "..." { + ... + } + metadata: + owasp: + - A10:2017 - Insufficient Logging & Monitoring + - A09:2021 - Security Logging and Monitoring Failures + cwe: + - 'CWE-778: Insufficient Logging' + category: security + technology: + - terraform + - azure + references: + - https://owasp.org/Top10/A09_2021-Security_Logging_and_Monitoring_Failures + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.azure.security.appservice.azure-appservice-http-logging-enabled.azure-appservice-http-logging-enabled + message: >- + Ensure that App service enables HTTP logging + patterns: + - pattern: resource + - pattern-not-inside: | + resource "azurerm_app_service" "..." { + ... + logs { + ... + http_logs { + ... + } + } + ... + } + - pattern-not-inside: | + resource "azurerm_app_service" "..." { + ... + logs { + ... + dynamic "http_logs" { + ... + } + } + ... + } + - pattern-inside: | + resource "azurerm_app_service" "..." { + ... + } + metadata: + owasp: + - A10:2017 - Insufficient Logging & Monitoring + - A09:2021 - Security Logging and Monitoring Failures + cwe: + - 'CWE-778: Insufficient Logging' + category: security + technology: + - terraform + - azure + references: + - https://owasp.org/Top10/A09_2021-Security_Logging_and_Monitoring_Failures + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.azure.security.appservice.azure-appservice-https-only.azure-appservice-https-only + message: >- + Ensure web app redirects all HTTP traffic to HTTPS in Azure App Service Slot + patterns: + - pattern: resource + - pattern-not-inside: | + resource "azurerm_app_service" "..." { + ... + https_only = true + ... + } + - pattern-inside: | + resource "azurerm_app_service" "..." { + ... + } + metadata: + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + cwe: + - 'CWE-319: Cleartext Transmission of Sensitive Information' + category: security + technology: + - terraform + - azure + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - vuln + likelihood: LOW + impact: MEDIUM + confidence: MEDIUM + languages: [hcl] + severity: WARNING +- id: terraform.azure.security.appservice.azure-appservice-identity.azure-appservice-identity + message: >- + Ensure App Service Authentication is set on Azure App Service + patterns: + - pattern: resource + - pattern-not-inside: | + resource "azurerm_app_service" "..." { + ... + client_cert_enabled = true + identity { + ... + } + ... + } + - pattern-inside: | + resource "azurerm_app_service" "..." { + ... + } + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - azure + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.azure.security.appservice.azure-appservice-identityprovider-enabled.azure-appservice-identityprovider-enabled + message: >- + Ensure that Managed identity provider is enabled for app services + patterns: + - pattern: resource + - pattern-not-inside: | + resource "azurerm_app_service" "..." { + ... + identity { + ... + type = "SystemAssigned" + ... + } + ... + } + - pattern-inside: | + resource "azurerm_app_service" "..." { + ... + } + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - azure + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.azure.security.appservice.azure-appservice-min-tls-version.azure-appservice-min-tls-version + message: >- + Ensure web app is using the latest version of TLS encryption + patterns: + - pattern-either: + - pattern: | + "1.0" + - pattern: | + "1.1" + - pattern-inside: min_tls_version = ... + - pattern-inside: | + $RESOURCE "azurerm_app_service" "..." { + ... + } + metadata: + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + cwe: + - 'CWE-326: Inadequate Encryption Strength' + category: security + technology: + - terraform + - azure + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: MEDIUM + languages: [hcl] + severity: WARNING +- id: terraform.azure.security.azure-automation-encrypted.azure-automation-encrypted + patterns: + - pattern-either: + - pattern-inside: | + resource "azurerm_automation_variable_string" "..." { + ... + } + - pattern-inside: | + resource "azurerm_automation_variable_datetime" "..." { + ... + } + - pattern-inside: | + resource "azurerm_automation_variable_int" "..." { + ... + } + - pattern-not-inside: | + resource "azurerm_automation_variable_string" "..." { + ... + encrypted = true + ... + } + - pattern-not-inside: | + resource "azurerm_automation_variable_datetime" "..." { + ... + encrypted = true + ... + } + - pattern-not-inside: | + resource "azurerm_automation_variable_int" "..." { + ... + encrypted = true + ... + } + message: Ensure that Automation account variables are encrypted + languages: [hcl] + severity: WARNING + metadata: + owasp: + - A03:2017 - Sensitive Data Exposure + cwe: + - 'CWE-320: CWE CATEGORY: Key Management Errors' + category: security + technology: + - terraform + - azure + + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW +- id: terraform.azure.security.azure-batchaccount-uses-keyvault-encrpytion.azure-batchaccount-uses-keyvault-encrpytion + message: >- + Ensure that Azure Batch account uses key vault to encrypt data + patterns: + - pattern: resource + - pattern-not-inside: | + resource "azurerm_batch_account" "..." { + ... + key_vault_reference { + ... + } + ... + } + - pattern-inside: | + resource "azurerm_batch_account" "..." { + ... + } + metadata: + owasp: + - A03:2017 - Sensitive Data Exposure + cwe: + - 'CWE-320: CWE CATEGORY: Key Management Errors' + category: security + technology: + - terraform + - azure + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.azure.security.azure-cognitiveservices-disables-public-network.azure-cognitiveservices-disables-public-network + message: >- + Ensure that Cognitive Services accounts disable public network access + patterns: + - pattern: resource + - pattern-not-inside: | + resource "azurerm_cognitive_account" "..." { + ... + public_network_access_enabled = false + ... + } + - pattern-inside: | + resource "azurerm_cognitive_account" "..." { + ... + } + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - azure + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.azure.security.azure-containergroup-deployed-into-virtualnetwork.azure-containergroup-deployed-into-virtualnetwork + message: >- + Ensure that Azure Container group is deployed into virtual network + patterns: + - pattern: resource + - pattern-not-inside: | + resource "azurerm_container_group" "..." { + ... + container { + ... + } + network_profile_id = "..." + ... + } + - pattern-inside: | + resource "azurerm_container_group" "..." { + ... + container { + ... + } + ... + } + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - azure + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.azure.security.azure-cosmosdb-accounts-restricted-access.azure-cosmosdb-accounts-restricted-access + message: >- + Ensure Cosmos DB accounts have restricted access + patterns: + - pattern: resource + - pattern-not-inside: | + resource "azurerm_cosmosdb_account" "..." { + ... + public_network_access_enabled = false + ... + } + - pattern-not-inside: | + resource "azurerm_cosmosdb_account" "..." { + ... + is_virtual_network_filter_enabled = true + virtual_network_rule = ... + ... + } + - pattern-not-inside: | + resource "azurerm_cosmosdb_account" "..." { + ... + is_virtual_network_filter_enabled = true + ip_range_filter = [...] + ... + } + - pattern-inside: | + resource "azurerm_cosmosdb_account" "..." { + ... + } + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - azure + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.azure.security.azure-cosmosdb-disable-access-key-write.azure-cosmosdb-disable-access-key-write + message: >- + Ensure that Cosmos DB accounts have access key write capability disabled + patterns: + - pattern: resource + - pattern-not-inside: | + resource "azurerm_cosmosdb_account" "..." { + ... + access_key_metadata_writes_enabled = false + ... + } + - pattern-inside: | + resource "azurerm_cosmosdb_account" "..." { + ... + } + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - azure + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.azure.security.azure-cosmosdb-disables-public-network.azure-cosmosdb-disables-public-network + message: >- + Ensure that Azure Cosmos DB disables public network access + patterns: + - pattern: resource + - pattern-not-inside: | + resource "azurerm_cosmosdb_account" "..." { + ... + public_network_access_enabled = false + ... + } + - pattern-inside: | + resource "azurerm_cosmosdb_account" "..." { + ... + } + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - azure + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.azure.security.azure-cosmosdb-have-cmk.azure-cosmosdb-have-cmk + message: >- + Ensure that Cosmos DB accounts have customer-managed keys to encrypt data at rest + patterns: + - pattern: resource + - pattern-not-inside: | + resource "azurerm_cosmosdb_account" "..." { + ... + key_vault_key_id = ... + ... + } + - pattern-inside: | + resource "azurerm_cosmosdb_account" "..." { + ... + } + metadata: + owasp: + - A03:2017 - Sensitive Data Exposure + cwe: + - 'CWE-320: CWE CATEGORY: Key Management Errors' + category: security + technology: + - terraform + - azure + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.azure.security.azure-customrole-definition-subscription-owner.azure-customrole-definition-subscription-owner + message: >- + Ensure that no custom subscription owner roles are created + patterns: + - pattern: | + ["*"] + - pattern-inside: | + resource "azurerm_role_definition" "..." { + permissions { + ... + } + } + - pattern-inside: actions = ... + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - azure + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.azure.security.azure-dataexplorer-double-encryption-enabled.azure-dataexplorer-double-encryption-enabled + message: >- + Ensure that Azure Data Explorer uses double encryption + patterns: + - pattern: resource + - pattern-not-inside: | + resource "azurerm_kusto_cluster" "..." { + ... + double_encryption_enabled = true + ... + } + - pattern-inside: | + resource "azurerm_kusto_cluster" "..." { + ... + } + metadata: + owasp: + - A03:2017 - Sensitive Data Exposure + cwe: + - 'CWE-320: CWE CATEGORY: Key Management Errors' + category: security + technology: + - terraform + - azure + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.azure.security.azure-dataexplorer-uses-disk-encryption.azure-dataexplorer-uses-disk-encryption + message: >- + Ensure that Azure Data Explorer uses disk encryption + patterns: + - pattern: resource + - pattern-not-inside: | + resource "azurerm_kusto_cluster" "..." { + ... + enable_disk_encryption = true + ... + } + - pattern-inside: | + resource "azurerm_kusto_cluster" "..." { + ... + } + metadata: + owasp: + - A03:2017 - Sensitive Data Exposure + cwe: + - 'CWE-320: CWE CATEGORY: Key Management Errors' + category: security + technology: + - terraform + - azure + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.azure.security.azure-datafactory-no-public-network-access.azure-datafactory-no-public-network-access + message: >- + Ensure that Azure Data factory public network access is disabled + patterns: + - pattern: resource + - pattern-not-inside: | + resource "azurerm_data_factory" "..." { + ... + public_network_enabled = false + ... + } + - pattern-inside: | + resource "azurerm_data_factory" "..." { + ... + } + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - azure + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.azure.security.azure-datafactory-uses-git-repository.azure-datafactory-uses-git-repository + message: >- + Ensure that Azure Data Factory uses Git repository for source control + patterns: + - pattern: resource + - pattern-not-inside: | + resource "azurerm_data_factory" "..." { + ... + github_configuration { + ... + } + ... + } + - pattern-not-inside: | + resource "azurerm_data_factory" "..." { + ... + vsts_configuration { + ... + } + ... + } + - pattern-inside: | + resource "azurerm_data_factory" "..." { + ... + } + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - azure + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.azure.security.azure-datalake-store-encryption.azure-datalake-store-encryption + message: >- + Ensure that Data Lake Store accounts enables encryption + patterns: + - pattern: resource + - pattern-not-inside: | + resource "azurerm_data_lake_store" "..." { + ... + encryption_state = "Enabled" + ... + } + - pattern-inside: | + resource "azurerm_data_lake_store" "..." { + ... + } + metadata: + owasp: + - A03:2017 - Sensitive Data Exposure + cwe: + - 'CWE-320: CWE CATEGORY: Key Management Errors' + category: security + technology: + - terraform + - azure + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.azure.security.azure-eventgrid-domain-network-access.azure-eventgrid-domain-network-access + message: >- + Ensure that Azure Event Grid Domain public network access is disabled + patterns: + - pattern: resource + - pattern-not-inside: | + resource "azurerm_eventgrid_domain" "..." { + ... + public_network_access_enabled = false + ... + } + - pattern-inside: | + resource "azurerm_eventgrid_domain" "..." { + ... + } + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - azure + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.azure.security.azure-functionapp-disallow-cors.azure-functionapp-disallow-cors + patterns: + - pattern: | + ["*"] + - pattern-inside: allowed_origins = ... + - pattern-inside: | + $RESOURCE "azurerm_function_app" "..." { + ... + } + message: ensure that CORS disallows all resources to access Function app + languages: [hcl] + severity: WARNING + metadata: + owasp: + - A05:2021 - Security Misconfiguration + cwe: + - 'CWE-942: Permissive Cross-domain Policy with Untrusted Domains' + category: security + technology: + - terraform + - azure + references: + - https://owasp.org/Top10/A05_2021-Security_Misconfiguration + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW +- id: terraform.azure.security.azure-functionapps-enable-auth.azure-functionapps-enable-auth + message: >- + Ensure that function apps enables Authentication + patterns: + - pattern: resource + - pattern-not-inside: | + resource "azurerm_function_app" "..." { + ... + auth_settings { + ... + enabled = true + ... + } + ... + } + - pattern-inside: | + resource "azurerm_function_app" "..." { + ... + } + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - azure + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.azure.security.azure-instance-extensions.azure-instance-extensions + message: >- + Ensure Virtual Machine Extensions are not Installed + patterns: + - pattern: resource + - pattern-either: + - pattern-inside: | + resource "azurerm_linux_virtual_machine" "..." { + ... + } + - pattern-inside: | + resource "azurerm_windows_virtual_machine" "..." { + ... + } + - pattern-not-inside: | + resource "azurerm_linux_virtual_machine" "..." { + ... + allow_extension_operations = false + ... + } + - pattern-not-inside: | + resource "azurerm_windows_virtual_machine" "..." { + ... + allow_extension_operations = false + ... + } + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - azure + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.azure.security.azure-iot-no-public-network-access.azure-iot-no-public-network-access + message: >- + Ensure that Azure IoT Hub disables public network access + patterns: + - pattern: resource + - pattern-inside: | + resource "azurerm_iothub" "..." { + ... + public_network_access_enabled = true + ... + } + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - azure + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.azure.security.azure-key-backedby-hsm.azure-key-backedby-hsm + message: >- + Ensure that key vault key is backed by HSM + patterns: + - pattern: resource + - pattern-not-inside: | + resource "azurerm_key_vault_key" "..." { + ... + key_type = "EC-HSM" + ... + } + - pattern-not-inside: | + resource "azurerm_key_vault_key" "..." { + ... + key_type = "RSA-HSM" + ... + } + - pattern-inside: | + resource "azurerm_key_vault_key" "..." { + ... + } + metadata: + owasp: + - A03:2017 - Sensitive Data Exposure + cwe: + - 'CWE-320: CWE CATEGORY: Key Management Errors' + category: security + technology: + - terraform + - azure + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.azure.security.azure-key-no-expiration-date.azure-key-no-expiration-date + message: >- + Ensure that the expiration date is set on all keys + patterns: + - pattern: resource + - pattern-not-inside: | + resource "azurerm_key_vault_key" "..." { + ... + expiration_date = "..." + ... + } + - pattern-inside: | + resource "azurerm_key_vault_key" "..." { + ... + } + metadata: + owasp: + - A03:2017 - Sensitive Data Exposure + cwe: + - 'CWE-320: CWE CATEGORY: Key Management Errors' + category: security + technology: + - terraform + - azure + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - vuln + likelihood: LOW + impact: LOW + confidence: MEDIUM + languages: [hcl] + severity: WARNING +- id: terraform.azure.security.azure-managed-disk-encryption-set.azure-managed-disk-encryption-set + message: >- + Ensure that managed disks use a specific set of disk encryption sets for the customer-managed key + encryption + patterns: + - pattern: resource + - pattern-not-inside: | + resource "azurerm_managed_disk" "..." { + ... + disk_encryption_set_id = ... + ... + } + - pattern-inside: | + resource "azurerm_managed_disk" "..." { + ... + } + metadata: + owasp: + - A03:2017 - Sensitive Data Exposure + cwe: + - 'CWE-320: CWE CATEGORY: Key Management Errors' + category: security + technology: + - terraform + - azure + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.azure.security.azure-managed-disk-encryption.azure-managed-disk-encryption + message: >- + Ensure Azure managed disk has encryption enabled + patterns: + - pattern: resource + - pattern-inside: | + resource "azurerm_managed_disk" "..." { + ... + encryption_settings { + ... + enabled = false + ... + } + ... + } + metadata: + owasp: + - A03:2017 - Sensitive Data Exposure + cwe: + - 'CWE-320: CWE CATEGORY: Key Management Errors' + category: security + technology: + - terraform + - azure + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.azure.security.azure-mariadb-public-access-disabled.azure-mariadb-public-access-disabled + message: >- + Ensure public network access enabled is set to False for MariaDB servers + patterns: + - pattern: resource + - pattern-inside: | + resource "azurerm_mariadb_server" "..." { + ... + } + - pattern-not-inside: | + resource "azurerm_mariadb_server" "..." { + ... + public_network_access_enabled = false + ... + } + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - azure + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.azure.security.azure-monitor-log-profile-retention-days.azure-monitor-log-profile-retention-days + message: Ensure that Activity Log Retention is set 365 days or greater + patterns: + - pattern: resource + - pattern-either: + - pattern-inside: | + resource "azurerm_monitor_log_profile" "..." { + ... + retention_policy { + ... + enabled = true + days = $DAYS + ... + } + ... + } + - pattern-not-inside: | + resource "azurerm_monitor_log_profile" "..." { + ... + retention_policy { + ... + enabled = false + days = 0 + ... + } + ... + } + - metavariable-comparison: + metavariable: $DAYS + comparison: $DAYS < 365 + metadata: + category: best-practice + technology: + - terraform + - azure + languages: + - hcl + severity: WARNING +- id: terraform.azure.security.azure-mssql-service-mintls-version.azure-mssql-service-mintls-version + message: >- + Ensure MSSQL is using the latest version of TLS encryption + patterns: + - pattern-either: + - pattern: | + "1.0" + - pattern: | + "1.1" + - pattern-inside: minimum_tls_version = ... + - pattern-inside: | + $RESOURCE "azurerm_mssql_server" "..." { + ... + } + metadata: + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + cwe: + - 'CWE-326: Inadequate Encryption Strength' + category: security + technology: + - terraform + - azure + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - vuln + likelihood: LOW + impact: MEDIUM + confidence: MEDIUM + languages: [hcl] + severity: WARNING +- id: terraform.azure.security.azure-mysql-encryption-enabled.azure-mysql-encryption-enabled + message: >- + Ensure that MySQL server enables infrastructure encryption + patterns: + - pattern: resource + - pattern-inside: | + resource "azurerm_mysql_server" "..." { + ... + } + - pattern-not-inside: | + resource "azurerm_mysql_server" "..." { + ... + infrastructure_encryption_enabled = true + ... + } + metadata: + owasp: + - A03:2017 - Sensitive Data Exposure + cwe: + - 'CWE-320: CWE CATEGORY: Key Management Errors' + category: security + technology: + - terraform + - azure + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - vuln + likelihood: LOW + impact: MEDIUM + confidence: MEDIUM + languages: [hcl] + severity: WARNING +- id: terraform.azure.security.azure-mysql-mintls-version.azure-mysql-mintls-version + message: >- + Ensure MySQL is using the latest version of TLS encryption + patterns: + - pattern-either: + - pattern: | + "TLS1_0" + - pattern: | + "TLS1_1" + - pattern-inside: ssl_minimal_tls_version_enforced = ... + - pattern-inside: | + $RESOURCE "azurerm_mysql_server" "..." { + ... + } + metadata: + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + cwe: + - 'CWE-326: Inadequate Encryption Strength' + category: security + technology: + - terraform + - azure + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - vuln + likelihood: LOW + impact: MEDIUM + confidence: MEDIUM + languages: [hcl] + severity: WARNING +- id: terraform.azure.security.azure-mysql-public-access-disabled.azure-mysql-public-access-disabled + message: >- + Ensure public network access enabled is set to False for MySQL servers + patterns: + - pattern: resource + - pattern-inside: | + resource "azurerm_mysql_server" "..." { + ... + } + - pattern-not-inside: | + resource "azurerm_mysql_server" "..." { + ... + public_network_access_enabled = false + ... + } + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - azure + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.azure.security.azure-network-watcher-flowlog-period.azure-network-watcher-flowlog-period + message: Ensure that Network Security Group Flow Log retention period is 90 days + or greater + patterns: + - pattern: resource + - pattern-inside: | + resource "azurerm_network_watcher_flow_log" "..." { + ... + retention_policy { + ... + enabled = true + days = $DAYS + ... + } + ... + } + - pattern-not-inside: | + resource "azurerm_network_watcher_flow_log" "..." { + ... + retention_policy { + ... + enabled = true + days = 0 + ... + } + ... + } + - metavariable-comparison: + metavariable: $DAYS + comparison: $DAYS < 90 + metadata: + category: best-practice + technology: + - terraform + - azure + languages: + - hcl + severity: WARNING +- id: terraform.azure.security.azure-postgresql-encryption-enabled.azure-postgresql-encryption-enabled + message: >- + Ensure that PostgreSQL server enables infrastructure encryption + patterns: + - pattern: resource + - pattern-inside: | + resource "azurerm_postgresql_server" "..." { + ... + } + - pattern-not-inside: | + resource "azurerm_postgresql_server" "..." { + ... + infrastructure_encryption_enabled = true + ... + } + metadata: + owasp: + - A03:2017 - Sensitive Data Exposure + cwe: + - 'CWE-320: CWE CATEGORY: Key Management Errors' + category: security + technology: + - terraform + - azure + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.azure.security.azure-postgresql-min-tls-version.azure-postgresql-min-tls-version + message: >- + Ensure PostgreSQL is using the latest version of TLS encryption + patterns: + - pattern-either: + - pattern: | + "TLS1_2" + - pattern: | + "TLS1_1" + - pattern: | + "TLS1_0" + - pattern-inside: ssl_minimal_tls_version_enforced = ... + - pattern-inside: | + $RESOURCE "azurerm_postgresql_server" "..." { + ... + } + - pattern-not-inside: | + $RESOURCE "azurerm_postgresql_server" "..." { + ... + ssl_enforcement_enabled = true + ... + } + metadata: + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + cwe: + - 'CWE-326: Inadequate Encryption Strength' + category: security + technology: + - terraform + - azure + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.azure.security.azure-postgresql-server-public-access-disabled.azure-postgresql-server-public-access-disabled + message: >- + Ensure public network access enabled is set to False for PostgreSQL servers + patterns: + - pattern: resource + - pattern-inside: | + resource "azurerm_postgresql_server" "..." { + ... + } + - pattern-not-inside: | + resource "azurerm_postgresql_server" "..." { + ... + public_network_access_enabled = false + ... + } + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - azure + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.azure.security.azure-redis-cache-enable-non-ssl-port.azure-redis-cache-enable-non-ssl-port + message: >- + Ensure that only SSL are enabled for Cache for Redis + patterns: + - pattern: resource + - pattern-inside: | + resource "azurerm_redis_cache" "..." { + ... + enable_non_ssl_port = true + ... + } + metadata: + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + cwe: + - 'CWE-319: Cleartext Transmission of Sensitive Information' + category: security + technology: + - terraform + - azure + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.azure.security.azure-redis-cache-public-network-access-enabled.azure-redis-cache-public-network-access-enabled + message: >- + Ensure that Azure Cache for Redis disables public network access + patterns: + - pattern: resource + - pattern-inside: | + resource "azurerm_redis_cache" "..." { + ... + } + - pattern-not-inside: | + resource "azurerm_redis_cache" "..." { + ... + public_network_access_enabled = false + ... + } + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - azure + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.azure.security.azure-remote-debugging-not-enabled.azure-remote-debugging-not-enabled + message: >- + Ensure that remote debugging is not enabled for app services + patterns: + - pattern: resource + - pattern-inside: | + resource "azurerm_app_service" "..." { + ... + remote_debugging_enabled = true + ... + } + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - azure + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.azure.security.azure-scale-set-password.azure-scale-set-password + message: >- + Ensure that Virtual machine does not enable password authentication + patterns: + - pattern: resource + - pattern-inside: | + resource "azurerm_linux_virtual_machine_scale_set" "..." { + ... + } + - pattern-not-inside: | + resource "azurerm_linux_virtual_machine_scale_set" "..." { + ... + disable_password_authentication = true + ... + } + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - azure + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.azure.security.azure-search-publicnetwork-access-disabled.azure-search-publicnetwork-access-disabled + message: >- + Ensure that Azure Cognitive Search disables public network access + patterns: + - pattern: resource + - pattern-inside: | + resource "azurerm_search_service" "..." { + ... + } + - pattern-not-inside: | + resource "azurerm_search_service" "..." { + ... + public_network_access_enabled = false + ... + } + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - azure + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.azure.security.azure-service-fabric-cluster-protection-level.azure-service-fabric-cluster-protection-level + message: >- + Ensure that Service Fabric use three levels of protection available + patterns: + - pattern: resource + - pattern-inside: | + resource "azurerm_service_fabric_cluster" "..." { + ... + } + - pattern-not-inside: | + resource "azurerm_service_fabric_cluster" "..." { + ... + fabric_settings { + name = "Security" + parameters = { + ... + name = "ClusterProtectionLevel" + value = "EncryptAndSign" + ... + } + ... + } + ... + } + metadata: + owasp: + - A03:2017 - Sensitive Data Exposure + cwe: + - 'CWE-320: CWE CATEGORY: Key Management Errors' + category: security + technology: + - terraform + - azure + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.azure.security.azure-sqlserver-no-public-access.azure-sqlserver-no-public-access + message: >- + Ensure no SQL Databases allow ingress from 0.0.0.0/0 (ANY IP) + patterns: + - pattern: resource + - pattern-inside: | + resource "azurerm_mysql_firewall_rule" "..." { + ... + start_ip_address = "0.0.0.0" + end_ip_address = "255.255.255.255" + ... + } + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - azure + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.azure.security.azure-sqlserver-public-access-disabled.azure-sqlserver-public-access-disabled + message: >- + Ensure that SQL server disables public network access + patterns: + - pattern: resource + - pattern-inside: | + resource "azurerm_mssql_server" "..." { + ... + } + - pattern-not-inside: | + resource "azurerm_mssql_server" "..." { + ... + public_network_access_enabled = false + ... + } + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - azure + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.azure.security.azure-storage-account-disable-public-access.azure-storage-account-disable-public-access + message: >- + Ensure default network access rule for Storage Accounts is set to deny + patterns: + - pattern: resource + - pattern-inside: | + resource "azurerm_storage_account" "..." { + ... + allow_blob_public_access = true + ... + } + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - azure + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.azure.security.azure-storage-account-minimum-tlsversion.azure-storage-account-minimum-tlsversion + message: >- + Ensure Storage Account is using the latest version of TLS encryption + patterns: + - pattern: resource + - pattern-inside: | + resource "azurerm_storage_account" "..." { + ... + } + - pattern-not-inside: | + resource "azurerm_storage_account" "..." { + ... + min_tls_version = "TLS1_2" + ... + } + - pattern-not-inside: | + resource "azurerm_storage_account" "..." { + ... + min_tls_version = "TLS1_3" + ... + } + metadata: + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + cwe: + - 'CWE-326: Inadequate Encryption Strength' + category: security + technology: + - terraform + - azure + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.azure.security.azure-storage-blob-service-container-private-access.azure-storage-blob-service-container-private-access + message: >- + Ensure that Public access level is set to Private for blob containers + patterns: + - pattern: resource + - pattern-inside: | + resource "azurerm_storage_container" "..." { + ... + } + - pattern-not-inside: | + resource "azurerm_storage_container" "..." { + ... + container_access_type = "private" + ... + } + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - azure + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.azure.security.azure-storage-sync-public-access-disabled.azure-storage-sync-public-access-disabled + message: >- + Ensure that Azure File Sync disables public network access + patterns: + - pattern: resource + - pattern-inside: | + resource "azurerm_storage_sync" "..." { + ... + } + - pattern-not-inside: | + resource "azurerm_storage_sync" "..." { + ... + incoming_traffic_policy = AllowVirtualNetworksOnly + ... + } + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - azure + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.azure.security.azure-vmencryption-at-host-enabled.azure-vmencryption-at-host-enabled + message: >- + Ensure that Virtual machine scale sets have encryption at host enabled + patterns: + - pattern: resource + - pattern-either: + - pattern-inside: | + resource "azurerm_windows_virtual_machine_scale_set" "..." { + ... + } + - pattern-inside: | + resource "azurerm_linux_virtual_machine_scale_set" "..." { + ... + } + - pattern-not-inside: | + resource "azurerm_windows_virtual_machine_scale_set" "..." { + ... + encryption_at_host_enabled = true + ... + } + - pattern-not-inside: | + resource "azurerm_linux_virtual_machine_scale_set" "..." { + ... + encryption_at_host_enabled = true + ... + } + metadata: + owasp: + - A03:2017 - Sensitive Data Exposure + cwe: + - 'CWE-320: CWE CATEGORY: Key Management Errors' + category: security + technology: + - terraform + - azure + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.azure.security.functionapp.functionapp-authentication-enabled.functionapp-authentication-enabled + message: >- + Enabling authentication ensures that all communications in the application are authenticated. + The `auth_settings` block needs to be filled out with the appropriate auth backend settings + patterns: + - pattern: resource + - pattern-not-inside: | + resource "azurerm_function_app" "..." { + ... + auth_settings { + ... + enabled = true + ... + } + ... + } + - pattern-either: + - pattern-inside: | + resource "azurerm_function_app" "..." { + ... + } + - pattern-inside: | + resource "azurerm_function_app" "..." { + ... + auth_settings { + ... + enabled = false + ... + } + ... + } + metadata: + cwe: + - 'CWE-287: Improper Authentication' + category: security + technology: + - terraform + - azure + references: + - https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/function_app#enabled + owasp: + - A02:2017 - Broken Authentication + - A07:2021 - Identification and Authentication Failures + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: INFO +- id: terraform.azure.security.functionapp.functionapp-enable-http2.functionapp-enable-http2 + message: >- + Use the latest version of HTTP to ensure you are benefiting from security fixes. Add `http2_enabled + = true` to your function + app resource block + patterns: + - pattern: resource + - pattern-not-inside: | + resource "azurerm_function_app" "..." { + ... + site_config { + ... + http2_enabled = true + ... + } + ... + } + - pattern-either: + - pattern-inside: | + resource "azurerm_function_app" "..." { + ... + } + - pattern-inside: | + resource "azurerm_function_app" "..." { + ... + site_config { + ... + http2_enabled = false + ... + } + ... + } + metadata: + cwe: + - "CWE-444: Inconsistent Interpretation of HTTP Requests ('HTTP Request/Response Smuggling')" + category: security + technology: + - terraform + - azure + references: + - https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/function_app#http2_enabled + owasp: + - A04:2021 - Insecure Design + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: INFO +- id: terraform.azure.security.keyvault.keyvault-content-type-for-secret.keyvault-content-type-for-secret + message: >- + Key vault Secret should have a content type set + patterns: + - pattern: resource + - pattern-not-inside: | + resource "azurerm_key_vault_secret" "..." { + ... + content_type = "..." + ... + } + - pattern-inside: | + resource "azurerm_key_vault_secret" "..." { + ... + } + metadata: + category: correctness + technology: + - terraform + - azure + references: + - https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/key_vault_secret#content_type + - https://docs.microsoft.com/en-us/azure/key-vault/secrets/about-secrets + languages: [hcl] + severity: INFO +- id: terraform.azure.security.keyvault.keyvault-ensure-key-expires.keyvault-ensure-key-expires + message: >- + Ensure that the expiration date is set on all keys + patterns: + - pattern: resource + - pattern-not-inside: | + resource "azurerm_key_vault_key" "..." { + ... + expiration_date = "..." + ... + } + - pattern-inside: | + resource "azurerm_key_vault_key" "..." { + ... + } + metadata: + cwe: + - 'CWE-262: Not Using Password Aging' + category: security + technology: + - terraform + - azure + references: + - https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/key_vault_key#expiration_date + - https://docs.microsoft.com/en-us/powershell/module/az.keyvault/update-azkeyvaultkey?view=azps-5.8.0#example-1--modify-a-key-to-enable-it--and-set-the-expiration-date-and-tags + subcategory: + - vuln + likelihood: LOW + impact: MEDIUM + confidence: MEDIUM + languages: [hcl] + severity: INFO +- id: terraform.azure.security.keyvault.keyvault-ensure-secret-expires.keyvault-ensure-secret-expires + message: >- + Ensure that the expiration date is set on all secrets + patterns: + - pattern: resource + - pattern-not-inside: | + resource "azurerm_key_vault_secret" "..." { + ... + expiration_date = "..." + ... + } + - pattern-inside: | + resource "azurerm_key_vault_secret" "..." { + ... + } + metadata: + cwe: + - 'CWE-262: Not Using Password Aging' + category: security + technology: + - terraform + - azure + references: + - https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/key_vault_secret#expiration_date + - https://docs.microsoft.com/en-us/azure/key-vault/secrets/about-secrets + subcategory: + - vuln + likelihood: LOW + impact: MEDIUM + confidence: MEDIUM + languages: [hcl] + severity: INFO +- id: terraform.azure.security.keyvault.keyvault-purge-enabled.keyvault-purge-enabled + message: >- + Key vault should have purge protection enabled + patterns: + - pattern: resource + - pattern-not-inside: | + resource "azurerm_key_vault" "..." { + ... + purge_protection_enabled = true + ... + } + - pattern-either: + - pattern-inside: | + resource "azurerm_key_vault" "..." { + ... + } + - pattern-inside: | + resource "azurerm_key_vault" "..." { + ... + purge_protection_enabled = false + ... + } + metadata: + cwe: + - 'CWE-693: Protection Mechanism Failure' + category: security + technology: + - terraform + - azure + references: + - https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/key_vault#purge_protection_enabled + - https://docs.microsoft.com/en-us/azure/key-vault/general/soft-delete-overview#purge-protection + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + languages: [hcl] + severity: WARNING +- id: terraform.azure.security.keyvault.keyvault-specify-network-acl.keyvault-specify-network-acl + message: >- + Network ACLs allow you to reduce your exposure to risk by limiting what can access your key vault. + The default action of the Network ACL should be set to deny for when IPs are not matched. Azure services + can be allowed + to bypass. + patterns: + - pattern: resource + - pattern-not-inside: | + resource "azurerm_key_vault" "..." { + ... + network_acls { + ... + default_action = "Deny" + ... + } + ... + } + - pattern-either: + - pattern-inside: | + resource "azurerm_key_vault" "..." { + ... + } + - pattern-inside: | + resource "azurerm_key_vault" "..." { + ... + network_acls { + ... + default_action = "Allow" + ... + } + ... + } + metadata: + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - azure + references: + - https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/key_vault#network_acls + - https://docs.microsoft.com/en-us/azure/key-vault/general/network-security + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: ERROR +- id: terraform.azure.security.storage.storage-allow-microsoft-service-bypass.storage-allow-microsoft-service-bypass + message: >- + Some Microsoft services that interact with storage accounts operate from networks that can't be granted + access through + network rules. + To help this type of service work as intended, allow the set of trusted Microsoft services to bypass + the network rules + patterns: + - pattern-not-inside: | + resource "azurerm_storage_account" "..." { + ... + network_rules { + ... + bypass = ["...", "AzureServices"] + ... + } + ... + } + - pattern-not-inside: | + resource "azurerm_storage_account_network_rules" "..." { + ... + bypass = ["...", "AzureServices"] + ... + } + - pattern-either: + - pattern-inside: | + resource "azurerm_storage_account_network_rules" "..." { + ... + bypass = [$ANYTHING] + ... + } + - pattern-inside: | + resource "azurerm_storage_account" "..." { + ... + network_rules { + ... + bypass = [$ANYTHING] + ... + } + ... + } + metadata: + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - azure + references: + - https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/storage_account#bypass + - https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/storage_account_network_rules#bypass + - https://docs.microsoft.com/en-us/azure/storage/common/storage-network-security#trusted-microsoft-services + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.azure.security.storage.storage-default-action-deny.storage-default-action-deny + message: >- + Detected a Storage that was not configured to deny action by default. Add `default_action = "Deny"` + in your resource block. + patterns: + - pattern: resource + - pattern-not-inside: | + resource "azurerm_storage_account_network_rules" "..." { + ... + default_action = "Deny" + ... + } + - pattern-inside: | + resource "azurerm_storage_account_network_rules" "..." { + ... + default_action = "Allow" + ... + } + metadata: + cwe: + - 'CWE-16: CWE CATEGORY: Configuration' + category: security + technology: + - terraform + - azure + references: + - https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/storage_account_network_rules#default_action + - https://docs.microsoft.com/en-us/azure/firewall/rule-processing + owasp: + - A06:2017 - Security Misconfiguration + - A05:2021 - Security Misconfiguration + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: ERROR +- id: terraform.azure.security.storage.storage-enforce-https.storage-enforce-https + message: >- + Detected a Storage that was not configured to deny action by default. Add `enable_https_traffic_only + = true` + in your resource block. + patterns: + - pattern-not-inside: | + resource "azurerm_storage_account" "..." { + ... + enable_https_traffic_only = true + ... + } + - pattern-inside: | + resource "azurerm_storage_account" "..." { + ... + enable_https_traffic_only = false + ... + } + metadata: + cwe: + - 'CWE-319: Cleartext Transmission of Sensitive Information' + category: security + technology: + - terraform + - azure + references: + - https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/storage_account#enable_https_traffic_only + - https://docs.microsoft.com/en-us/azure/storage/common/storage-require-secure-transfer + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + subcategory: + - vuln + likelihood: LOW + impact: MEDIUM + confidence: MEDIUM + languages: [hcl] + severity: WARNING +- id: terraform.azure.security.storage.storage-queue-services-logging.storage-queue-services-logging + message: >- + Storage Analytics logs detailed information about successful and failed requests to a storage service. + This information can be used to monitor individual requests and to diagnose issues with a storage + service. + Requests are logged on a best-effort basis. + patterns: + - pattern-either: + - pattern-inside: | + resource "azurerm_storage_account" "..." { + ... + queue_properties { + ... + } + ... + } + - pattern-inside: | + resource "azurerm_storage_account" "..." { + ... + } + - pattern-not-inside: | + resource "azurerm_storage_account" "..." { + ... + queue_properties { + ... + logging { + ... + } + ... + } + ... + } + metadata: + cwe: + - 'CWE-778: Insufficient Logging' + category: security + technology: + - terraform + - azure + references: + - https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/storage_account#logging + - https://docs.microsoft.com/en-us/azure/storage/common/storage-analytics-logging?tabs=dotnet + owasp: + - A10:2017 - Insufficient Logging & Monitoring + - A09:2021 - Security Logging and Monitoring Failures + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.azure.security.storage.storage-use-secure-tls-policy.storage-use-secure-tls-policy + message: >- + Azure Storage currently supports three versions of the TLS protocol: 1.0, 1.1, and 1.2. + Azure Storage uses TLS 1.2 on public HTTPS endpoints, but TLS 1.0 and TLS 1.1 are still supported + for backward compatibility. + This check will warn if the minimum TLS is not set to TLS1_2. + patterns: + - pattern-either: + - pattern-inside: | + resource "azurerm_storage_account" "..." { + ... + min_tls_version = "$ANYTHING" + ... + } + - pattern-inside: | + resource "azurerm_storage_account" "..." { + ... + } + - pattern-not-inside: | + resource "azurerm_storage_account" "..." { + ... + min_tls_version = "TLS1_2" + ... + } + metadata: + cwe: + - 'CWE-326: Inadequate Encryption Strength' + category: security + technology: + - terraform + - azure + references: + - https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/storage_account#min_tls_version + - https://docs.microsoft.com/en-us/azure/storage/common/transport-layer-security-configure-minimum-version + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + languages: [hcl] + severity: ERROR +- id: terraform.gcp.best-practice.gcp-compute-shielded-vm.gcp-compute-shielded-vm + patterns: + - pattern: resource + - pattern-either: + - pattern-inside: | + resource "google_compute_instance" "..." { + ... + } + - pattern-inside: | + resource "google_compute_instance" "..." { + ... + shielded_instance_config { + ... + enable_integrity_monitoring = false + ... + } + ... + } + - pattern-not-inside: | + resource "google_compute_instance" "..." { + ... + shielded_instance_config { + ... + enable_integrity_monitoring = true + ... + } + ... + } + message: >- + Ensure Compute instances are launched with Shielded VM enabled + metadata: + category: best-practice + technology: + - terraform + - gcp + references: + - https://docs.bridgecrew.io/docs/google-cloud-policy-index + languages: [hcl] + severity: WARNING +- id: terraform.gcp.best-practice.gcp-compute-template-shielded-vm.gcp-compute-template-shielded-vm + patterns: + - pattern: resource + - pattern-inside: | + resource "google_compute_instance_template" "..." { + ... + shielded_instance_config { + ... + enable_integrity_monitoring = false + ... + } + ... + } + message: >- + Ensure Compute instances are launched with Shielded VM enabled + metadata: + category: best-practice + technology: + - terraform + - gcp + references: + - https://docs.bridgecrew.io/docs/google-cloud-policy-index + languages: [hcl] + severity: WARNING +- id: terraform.gcp.best-practice.gcp-dnssec-enabled.gcp-dnssec-enabled + patterns: + - pattern: resource + - pattern-inside: | + resource "google_dns_managed_zone" "..." { + ... + } + - pattern-not-inside: | + resource "google_dns_managed_zone" "..." { + ... + dnssec_config { + state = on + } + ... + } + message: >- + Ensure that RSASHA1 is not used for the zone-signing and key-signing keys in Cloud DNS DNSSEC + metadata: + category: best-practice + technology: + - terraform + - gcp + languages: [hcl] + severity: WARNING +- id: terraform.gcp.best-practice.gcp-gke-alias-ip-enabled.gcp-gke-alias-ip-enabled + patterns: + - pattern: resource + - pattern-inside: | + resource "google_container_cluster" "..." { + ... + } + - pattern-not-inside: | + resource "google_container_cluster" "..." { + ... + ip_allocation_policy { + ... + use_ip_aliases = "false" + ... + } + ... + } + message: >- + Ensure Kubernetes Cluster is created with Alias IP ranges enabled + metadata: + category: best-practice + technology: + - terraform + - gcp + languages: [hcl] + severity: WARNING +- id: terraform.gcp.best-practice.gcp-gke-binary-authorization.gcp-gke-binary-authorization + patterns: + - pattern: resource + - pattern-inside: | + resource "google_container_cluster" "..." { + ... + } + - pattern-not-inside: | + resource "google_container_cluster" "..." { + ... + enable_binary_authorization = true + ... + } + message: >- + Ensure use of Binary Authorization + metadata: + category: best-practice + technology: + - terraform + - gcp + languages: [hcl] + severity: WARNING +- id: terraform.gcp.best-practice.gcp-gke-enable-shielded-nodes.gcp-gke-enable-shielded-nodes + patterns: + - pattern: resource + - pattern-inside: | + resource "google_container_cluster" "..." { + ... + enable_shielded_nodes = false + ... + } + message: >- + Ensure Shielded GKE Nodes are Enabled + metadata: + category: best-practice + technology: + - terraform + - gcp + languages: [hcl] + severity: WARNING +- id: terraform.gcp.best-practice.gcp-gke-has-labels.gcp-gke-has-labels + patterns: + - pattern: resource + - pattern-inside: | + resource "google_container_cluster" "..." { + ... + } + - pattern-not-inside: | + resource "google_container_cluster" "..." { + ... + resource_labels = { + "..." = "..." + } + ... + } + message: >- + Ensure Kubernetes Clusters are configured with Labels + metadata: + category: best-practice + technology: + - terraform + - gcp + languages: [hcl] + severity: WARNING +- id: terraform.gcp.best-practice.gcp-gke-metadata-server-enabled.gcp-gke-metadata-server-enabled + patterns: + - pattern: resource + - pattern-inside: | + resource "google_container_cluster" "..." { + ... + } + - pattern-not-inside: | + resource "google_container_cluster" "..." { + ... + node_config { + ... + workload_metadata_config { + ... + node_metadata = "GKE_METADATA_SERVER" + ... + } + ... + } + ... + } + - pattern-not-inside: | + resource "google_container_cluster" "..." { + ... + node_config { + ... + workload_metadata_config { + ... + mode = "GKE_METADATA" + ... + } + ... + } + ... + } + - pattern-not-inside: | + resource "google_container_cluster" "..." { + ... + node_config { + ... + workload_metadata_config = ... + ... + } + ... + } + message: >- + Ensure the GKE Metadata Server is Enabled + metadata: + category: best-practice + technology: + - terraform + - gcp + languages: [hcl] + severity: WARNING +- id: terraform.gcp.best-practice.gcp-gke-nodepool-auto-repair-enabled.gcp-gke-nodepool-auto-repair-enabled + patterns: + - pattern: resource + - pattern-inside: | + resource "google_container_node_pool" "..." { + ... + management { + ... + auto_repair = false + ... + } + ... + } + message: >- + Ensure 'Automatic node repair' is enabled for Kubernetes Clusters + metadata: + category: best-practice + technology: + - terraform + - gcp + languages: [hcl] + severity: WARNING +- id: terraform.gcp.best-practice.gcp-gke-nodepool-auto-upgrade-enabled.gcp-gke-nodepool-auto-upgrade-enabled + patterns: + - pattern: resource + - pattern-inside: | + resource "google_container_node_pool" "..." { + ... + management { + ... + auto_upgrade = false + ... + } + ... + } + message: >- + Ensure 'Automatic node upgrade' is enabled for Kubernetes Clusters + metadata: + category: best-practice + technology: + - terraform + - gcp + languages: [hcl] + severity: WARNING +- id: terraform.gcp.best-practice.gcp-gke-nodepool-metadata-server-enabled.gcp-gke-nodepool-metadata-server-enabled + patterns: + - pattern: resource + - pattern-inside: | + resource "google_container_node_pool" "..." { + ... + } + - pattern-not-inside: | + resource "google_container_node_pool" "..." { + ... + node_config { + ... + workload_metadata_config { + ... + node_metadata = "GKE_METADATA_SERVER" + ... + } + ... + } + ... + } + - pattern-not-inside: | + resource "google_container_node_pool" "..." { + ... + node_config { + ... + workload_metadata_config { + ... + mode = "GKE_METADATA" + ... + } + ... + } + ... + } + message: >- + Ensure the GKE Metadata Server is Enabled + metadata: + category: best-practice + technology: + - terraform + - gcp + languages: [hcl] + severity: WARNING +- id: terraform.gcp.best-practice.gcp-gke-nodepool-secure-boot-for-shielded-nodes.gcp-gke-nodepool-secure-boot-for-shielded-nodes + patterns: + - pattern: resource + - pattern-inside: | + resource "google_container_node_pool" "..." { + ... + } + - pattern-not-inside: | + resource "google_container_node_pool" "..." { + ... + shielded_instance_config { + ... + enable_secure_boot = true + ... + } + ... + } + message: >- + Ensure Secure Boot for Shielded GKE Nodes is Enabled + metadata: + category: best-practice + technology: + - terraform + - gcp + languages: [hcl] + severity: WARNING +- id: terraform.gcp.best-practice.gcp-gke-sql-backup-configuration-enabled.gcp-gke-sql-backup-configuration-enabled + patterns: + - pattern: resource + - pattern-inside: | + resource "google_sql_database_instance" "..." { + ... + } + - pattern-not-inside: | + resource "google_sql_database_instance" "..." { + ... + settings { + ... + backup_configuration { + ... + enabled = true + ... + } + ... + } + ... + } + message: >- + Ensure all Cloud SQL database instance have backup configuration enabled + metadata: + category: best-practice + technology: + - terraform + - gcp + languages: [hcl] + severity: WARNING +- id: terraform.gcp.best-practice.gcp-gke-use-cos-image.gcp-gke-use-cos-image + patterns: + - pattern: resource + - pattern-inside: | + resource "google_container_node_pool" "..." { + ... + } + - pattern-not-inside: | + resource "google_container_node_pool" "..." { + ... + node_config { + ... + image_type = "COS" + } + ... + } + message: >- + Ensure Container-Optimized OS (cos) is used for Kubernetes Engine Clusters Node image + metadata: + category: best-practice + technology: + - terraform + - gcp + languages: [hcl] + severity: WARNING +- id: terraform.gcp.best-practice.gcp-ipv6-private-google-enabled.gcp-ipv6-private-google-enabled + patterns: + - pattern: resource + - pattern-inside: | + resource "google_compute_subnetwork" "..." { + ... + } + - pattern-not-inside: | + resource "google_compute_subnetwork" "..." { + ... + private_ipv6_google_access = "ENABLE_OUTBOUND_VM_ACCESS_TO_GOOGLE" + ... + } + - pattern-not-inside: | + resource "google_compute_subnetwork" "..." { + ... + private_ipv6_google_access = "ENABLE_BIDIRECTIONAL_ACCESS_TO_GOOGLE" + ... + } + message: >- + Ensure that Private google access is enabled for IPV6 + metadata: + category: best-practice + technology: + - terraform + - gcp + languages: [hcl] + severity: WARNING +- id: terraform.gcp.best-practice.gcp-mysql-local-in-file-off.gcp-mysql-local-in-file-off + patterns: + - pattern: resource + - pattern-inside: | + resource "google_sql_database_instance" "..." { + ... + database_flags { + ... + name = "local_infile" + value = "on" + ... + } + ... + } + message: >- + Ensure MySQL database 'local_infile' flag is set to 'off' + metadata: + category: best-practice + technology: + - terraform + - gcp + languages: [hcl] + severity: WARNING +- id: terraform.gcp.best-practice.gcp-postgresql-log-checkpoints.gcp-postgresql-log-checkpoints + patterns: + - pattern: resource + - pattern-inside: | + resource "google_sql_database_instance" "..." { + ... + database_flags { + ... + name = "log_checkpoints" + value = "off" + ... + } + ... + } + message: >- + Ensure PostgreSQL database 'log_checkpoints' flag is set to 'on' + metadata: + category: best-practice + technology: + - terraform + - gcp + languages: [hcl] + severity: WARNING +- id: terraform.gcp.best-practice.gcp-postgresql-log-connection.gcp-postgresql-log-connection + patterns: + - pattern: resource + - pattern-inside: | + resource "google_sql_database_instance" "..." { + ... + database_flags { + ... + name = "log_connections" + value = "off" + ... + } + ... + } + message: >- + Ensure PostgreSQL database 'log_connections' flag is set to 'on' + metadata: + category: best-practice + technology: + - terraform + - gcp + languages: [hcl] + severity: WARNING +- id: terraform.gcp.best-practice.gcp-postgresql-log-disconnection.gcp-postgresql-log-disconnection + patterns: + - pattern: resource + - pattern-inside: | + resource "google_sql_database_instance" "..." { + ... + database_flags { + ... + name = "log_disconnections" + value = "off" + ... + } + ... + } + message: >- + Ensure PostgreSQL database 'log_disconnections' flag is set to 'on' + metadata: + category: best-practice + technology: + - terraform + - gcp + languages: [hcl] + severity: WARNING +- id: terraform.gcp.best-practice.gcp-postgresql-log-lock-waits.gcp-postgresql-log-lock-waits + patterns: + - pattern: resource + - pattern-inside: | + resource "google_sql_database_instance" "..." { + ... + database_flags { + ... + name = "log_lock_waits" + value = "off" + ... + } + ... + } + message: >- + Ensure PostgreSQL database 'log_lock_waits' flag is set to 'on' + metadata: + category: best-practice + technology: + - terraform + - gcp + languages: [hcl] + severity: WARNING +- id: terraform.gcp.best-practice.gcp-postgresql-log-min-duration.gcp-postgresql-log-min-duration + patterns: + - pattern: resource + - pattern-inside: | + resource "google_sql_database_instance" "..." { + ... + database_flags { + ... + } + ... + } + - pattern-not-inside: | + resource "google_sql_database_instance" "..." { + ... + database_flags { + ... + name = "log_min_duration_statement" + value = "-1" + ... + } + ... + } + message: >- + Ensure PostgreSQL database 'log_min_duration_statement' flag is set to '-1' + metadata: + category: best-practice + technology: + - terraform + - gcp + languages: [hcl] + severity: WARNING +- id: terraform.gcp.best-practice.gcp-postgresql-log-min-message.gcp-postgresql-log-min-message + patterns: + - pattern: resource + - pattern-inside: | + resource "google_sql_database_instance" "..." { + ... + database_flags { + ... + name = "log_min_messages" + value = "$VALUE" + ... + } + ... + } + - metavariable-pattern: + metavariable: $VALUE + language: generic + patterns: + - pattern-not-regex: (?i)(DEBUG5|DEBUG4|DEBUG3|DEBUG2|DEBUG1|INFO|NOTICE|WARNING|ERROR|LOG|FATAL|PANIC) + message: Ensure PostgreSQL database 'log_min_messages' flag is set to a valid value + metadata: + category: best-practice + technology: + - terraform + - gcp + languages: + - hcl + severity: WARNING +- id: terraform.gcp.best-practice.gcp-postgresql-log-temp.gcp-postgresql-log-temp + patterns: + - pattern: resource + - pattern-inside: | + resource "google_sql_database_instance" "..." { + ... + database_flags { + ... + } + ... + } + - pattern-not-inside: | + resource "google_sql_database_instance" "..." { + ... + database_flags { + ... + name = "log_temp_files" + value = "0" + ... + } + ... + } + message: >- + Ensure PostgreSQL database 'log_temp_files' flag is set to '0' + metadata: + category: best-practice + technology: + - terraform + - gcp + languages: [hcl] + severity: WARNING +- id: terraform.gcp.best-practice.gcp-storage-versioning-enabled.gcp-storage-versioning-enabled + patterns: + - pattern: resource + - pattern-inside: | + resource "google_storage_bucket" "..." { + ... + } + - pattern-not-inside: | + resource "google_storage_bucket" "..." { + ... + versioning = { + enabled = true + } + ... + } + message: >- + Ensure Cloud storage has versioning enabled + metadata: + category: best-practice + technology: + - terraform + - gcp + languages: [hcl] + severity: WARNING +- id: terraform.gcp.security.gcp-artifact-registry-encrypted-with-cmk.gcp-artifact-registry-encrypted-with-cmk + patterns: + - pattern: | + resource "google_artifact_registry_repository" $ANYTHING { + ... + } + - pattern-not-inside: | + resource "google_artifact_registry_repository" $ANYTHING { + ... + kms_key_name = ... + ... + } + message: >- + Ensure Artifact Registry Repositories are encrypted with Customer Supplied Encryption Keys (CSEK) + metadata: + category: security + technology: + - terraform + - gcp + owasp: + - A03:2017 - Sensitive Data Exposure + cwe: + - 'CWE-320: CWE CATEGORY: Key Management Errors' + references: + - https://docs.bridgecrew.io/docs/google-cloud-policy-index + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.gcp.security.gcp-artifact-registry-private-repo-iam-binding.gcp-artifact-registry-private-repo-iam-binding + patterns: + - pattern: resource + - pattern-either: + - pattern-inside: | + resource "google_artifact_registry_repository_iam_binding" "..." { + ... + members = [ ..., "allAuthenticatedUsers", ...] + ... + } + - pattern-inside: | + resource "google_artifact_registry_repository_iam_binding" "..." { + ... + members = [ ..., "allUsers", ...] + ... + } + message: >- + Ensure that Artifact Registry repositories are not anonymously or publicly accessible + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - gcp + references: + - https://docs.bridgecrew.io/docs/google-cloud-policy-index + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.gcp.security.gcp-artifact-registry-private-repo-iam-member.gcp-artifact-registry-private-repo-iam-member + patterns: + - pattern: resource + - pattern-either: + - pattern-inside: | + resource "google_artifact_registry_repository_iam_member" "..." { + ... + member = "allUsers" + ... + } + - pattern-inside: | + resource "google_artifact_registry_repository_iam_member" "..." { + ... + member = "allAuthenticatedUsers" + ... + } + message: >- + Ensure that Artifact Registry repositories are not anonymously or publicly accessible + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - gcp + references: + - https://docs.bridgecrew.io/docs/google-cloud-policy-index + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.gcp.security.gcp-bigquery-dataset-encrypted-with-cmk.gcp-bigquery-dataset-encrypted-with-cmk + patterns: + - pattern: | + resource "google_bigquery_dataset" $ANYTHING { + ... + } + - pattern-not-inside: | + resource "google_bigquery_dataset" $ANYTHING { + ... + default_encryption_configuration { + ... + kms_key_name = ... + ... + } + ... + } + message: >- + Ensure that BigQuery datasets are not anonymously or publicly accessible + metadata: + category: security + technology: + - terraform + - gcp + owasp: + - A03:2017 - Sensitive Data Exposure + cwe: + - 'CWE-320: CWE CATEGORY: Key Management Errors' + references: + - https://docs.bridgecrew.io/docs/google-cloud-policy-index + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.gcp.security.gcp-bigquery-private-table-iam-binding.gcp-bigquery-private-table-iam-binding + patterns: + - pattern: resource + - pattern-either: + - pattern-inside: | + resource "google_bigquery_table_iam_binding" "..." { + ... + members = [ ..., "allAuthenticatedUsers", ...] + ... + } + - pattern-inside: | + resource "google_bigquery_table_iam_binding" "..." { + ... + members = [ ..., "allUsers", ...] + ... + } + message: >- + Ensure that BigQuery Tables are not anonymously or publicly accessible + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - gcp + references: + - https://docs.bridgecrew.io/docs/google-cloud-policy-index + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.gcp.security.gcp-bigquery-private-table-iam-member.gcp-bigquery-private-table-iam-member + patterns: + - pattern: resource + - pattern-either: + - pattern-inside: | + resource "google_bigquery_table_iam_member" "..." { + ... + member = "allAuthenticatedUsers" + ... + } + - pattern-inside: | + resource "google_bigquery_table_iam_member" "..." { + ... + member = "allUsers" + ... + } + message: >- + Ensure that BigQuery Tables are not anonymously or publicly accessible + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - gcp + references: + - https://docs.bridgecrew.io/docs/google-cloud-policy-index + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.gcp.security.gcp-bigquery-table-encrypted-with-cmk.gcp-bigquery-table-encrypted-with-cmk + patterns: + - pattern: | + resource "google_bigquery_table" $ANYTHING { + ... + } + - pattern-not-inside: | + resource "google_bigquery_table" $ANYTHING { + ... + encryption_configuration { + ... + kms_key_name = ... + ... + } + ... + } + message: >- + Ensure Big Query Tables are encrypted with Customer Supplied Encryption Keys (CSEK) + metadata: + category: security + technology: + - terraform + - gcp + owasp: + - A03:2017 - Sensitive Data Exposure + cwe: + - 'CWE-320: CWE CATEGORY: Key Management Errors' + references: + - https://docs.bridgecrew.io/docs/google-cloud-policy-index + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.gcp.security.gcp-bigtable-instance-encrypted-with-cmk.gcp-bigtable-instance-encrypted-with-cmk + patterns: + - pattern: | + resource "google_bigtable_instance" $ANYTHING { + ... + } + - pattern-not-inside: | + resource "google_bigtable_instance" $ANYTHING { + ... + cluster { + ... + kms_key_name = ... + ... + } + ... + } + message: >- + Ensure Big Table Instances are encrypted with Customer Supplied Encryption Keys (CSEK) + metadata: + category: security + technology: + - terraform + - gcp + owasp: + - A03:2017 - Sensitive Data Exposure + cwe: + - 'CWE-320: CWE CATEGORY: Key Management Errors' + references: + - https://docs.bridgecrew.io/docs/google-cloud-policy-index + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.gcp.security.gcp-build-workers-private.gcp-build-workers-private + patterns: + - pattern: resource + - pattern-inside: | + resource "google_cloudbuild_worker_pool" "..." { + ... + } + - pattern-not-inside: | + resource "google_cloudbuild_worker_pool" "..." { + ... + worker_config { + ... + no_external_ip = true + ... + } + ... + } + message: >- + Ensure Cloud build workers are private + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - gcp + references: + - https://docs.bridgecrew.io/docs/google-cloud-policy-index + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.gcp.security.gcp-cloud-storage-logging.gcp-cloud-storage-logging + patterns: + - pattern: | + resource "google_storage_bucket" $ANYTHING { + ... + } + - pattern-not-inside: | + resource "google_storage_bucket" $ANYTHING { + ... + logging { + log_bucket = ... + } + ... + } + message: Ensure bucket logs access. + languages: [hcl] + severity: WARNING + metadata: + owasp: + - A10:2017 - Insufficient Logging & Monitoring + - A09:2021 - Security Logging and Monitoring Failures + cwe: + - 'CWE-778: Insufficient Logging' + technology: + - terraform + - gcp + category: security + references: + - https://docs.bridgecrew.io/docs/google-cloud-policy-index + subcategory: + - vuln + likelihood: LOW + impact: LOW + confidence: MEDIUM +- id: terraform.gcp.security.gcp-compute-boot-disk-encryption.gcp-compute-boot-disk-encryption + patterns: + - pattern: | + resource "google_compute_instance" $ANYTHING { + ... + } + - pattern-not-inside: | + resource "google_compute_instance" $ANYTHING { + ... + boot_disk { + disk_encryption_key_raw = ... + } + ... + } + - pattern-not-inside: | + resource "google_compute_instance" $ANYTHING { + ... + boot_disk { + kms_key_self_link = ... + } + ... + } + message: Ensure VM disks for critical VMs are encrypted with Customer Supplied Encryption Keys (CSEK) + languages: [hcl] + severity: WARNING + metadata: + owasp: + - A03:2017 - Sensitive Data Exposure + - A04:2021 - Insecure Design + cwe: + - 'CWE-311: Missing Encryption of Sensitive Data' + technology: + - terraform + - gcp + category: security + references: + - https://docs.bridgecrew.io/docs/google-cloud-policy-index + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW +- id: terraform.gcp.security.gcp-compute-disk-encryption.gcp-compute-disk-encryption + patterns: + - pattern: | + resource "google_compute_disk" $ANYTHING { + ... + } + - pattern-not-inside: | + resource "google_compute_disk" $ANYTHING { + ... + disk_encryption_key { + raw_key = ... + } + ... + } + - pattern-not-inside: | + resource "google_compute_disk" $ANYTHING { + ... + disk_encryption_key { + kms_key_self_link = ... + } + ... + } + message: Ensure VM disks for critical VMs are encrypted with Customer Supplied Encryption Keys (CSEK) + languages: [hcl] + severity: WARNING + metadata: + owasp: + - A03:2017 - Sensitive Data Exposure + - A04:2021 - Insecure Design + cwe: + - 'CWE-311: Missing Encryption of Sensitive Data' + technology: + - terraform + - gcp + category: security + references: + - https://docs.bridgecrew.io/docs/google-cloud-policy-index + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW +- id: terraform.gcp.security.gcp-compute-firewall-unrestricted-ingress-20.gcp-compute-firewall-unrestricted-ingress-20 + patterns: + - pattern: resource + - pattern-either: + - pattern-inside: | + resource "google_compute_firewall" "..." { + ... + allow { + protocol = "tcp" + ports = [20] + } + source_ranges = ["0.0.0.0/0"] + ... + } + - pattern-inside: | + resource "google_compute_firewall" "..." { + ... + allow { + protocol = "tcp" + ports = [..., "20", ...] + } + source_ranges = ["0.0.0.0/0"] + ... + } + message: >- + Ensure Google compute firewall ingress does not allow unrestricted FTP access + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - gcp + references: + - https://docs.bridgecrew.io/docs/google-cloud-policy-index + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.gcp.security.gcp-compute-firewall-unrestricted-ingress-21.gcp-compute-firewall-unrestricted-ingress-21 + patterns: + - pattern: resource + - pattern-either: + - pattern-inside: | + resource "google_compute_firewall" "..." { + ... + allow { + protocol = "tcp" + ports = [21] + } + source_ranges = ["0.0.0.0/0"] + ... + } + - pattern-inside: | + resource "google_compute_firewall" "..." { + ... + allow { + protocol = "tcp" + ports = [..., "21", ...] + } + source_ranges = ["0.0.0.0/0"] + ... + } + message: >- + Ensure Google compute firewall ingress does not allow unrestricted FTP access + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - gcp + references: + - https://docs.bridgecrew.io/docs/google-cloud-policy-index + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.gcp.security.gcp-compute-firewall-unrestricted-ingress-22.gcp-compute-firewall-unrestricted-ingress-22 + patterns: + - pattern: resource + - pattern-either: + - pattern-inside: | + resource "google_compute_firewall" "..." { + ... + allow { + protocol = "tcp" + ports = [22] + } + source_ranges = ["0.0.0.0/0"] + ... + } + - pattern-inside: | + resource "google_compute_firewall" "..." { + ... + allow { + protocol = "tcp" + ports = [..., "22", ...] + } + source_ranges = ["0.0.0.0/0"] + ... + } + message: >- + Ensure Google compute firewall ingress does not allow unrestricted SSH access + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - gcp + references: + - https://docs.bridgecrew.io/docs/google-cloud-policy-index + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.gcp.security.gcp-compute-firewall-unrestricted-ingress-3306.gcp-compute-firewall-unrestricted-ingress-3306 + patterns: + - pattern: resource + - pattern-either: + - pattern-inside: | + resource "google_compute_firewall" "..." { + ... + allow { + protocol = "tcp" + ports = [3306] + } + source_ranges = ["0.0.0.0/0"] + ... + } + - pattern-inside: | + resource "google_compute_firewall" "..." { + ... + allow { + protocol = "tcp" + ports = [..., "3306", ...] + } + source_ranges = ["0.0.0.0/0"] + ... + } + message: >- + Ensure Google compute firewall ingress does not allow unrestricted MySQL access + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - gcp + references: + - https://docs.bridgecrew.io/docs/google-cloud-policy-index + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.gcp.security.gcp-compute-firewall-unrestricted-ingress-3389.gcp-compute-firewall-unrestricted-ingress-3389 + patterns: + - pattern: resource + - pattern-either: + - pattern-inside: | + resource "google_compute_firewall" "..." { + ... + allow { + protocol = "tcp" + ports = [3389] + } + source_ranges = ["0.0.0.0/0"] + ... + } + - pattern-inside: | + resource "google_compute_firewall" "..." { + ... + allow { + protocol = "tcp" + ports = [..., "3389", ...] + } + source_ranges = ["0.0.0.0/0"] + ... + } + message: >- + Ensure Google compute firewall ingress does not allow unrestricted RDP access + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - gcp + references: + - https://docs.bridgecrew.io/docs/google-cloud-policy-index + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.gcp.security.gcp-compute-firewall-unrestricted-ingress-80.gcp-compute-firewall-unrestricted-ingress-80 + patterns: + - pattern: resource + - pattern-either: + - pattern-inside: | + resource "google_compute_firewall" "..." { + ... + allow { + protocol = "tcp" + ports = [80] + } + source_ranges = ["0.0.0.0/0"] + ... + } + - pattern-inside: | + resource "google_compute_firewall" "..." { + ... + allow { + protocol = "tcp" + ports = [..., "80", ...] + } + source_ranges = ["0.0.0.0/0"] + ... + } + message: >- + Ensure Google compute firewall ingress does not allow unrestricted HTTP access + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - gcp + references: + - https://docs.bridgecrew.io/docs/google-cloud-policy-index + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.gcp.security.gcp-compute-ip-forward.gcp-compute-ip-forward + patterns: + - pattern: resource + - pattern-inside: | + resource "google_compute_instance" "..." { + ... + can_ip_forward = true + ... + } + message: >- + Ensure that IP forwarding is not enabled on Instances. This lets the instance act as a traffic router + and + receive traffic not intended for it, which may route traffic through unintended passages. + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - gcp + references: + - https://docs.bridgecrew.io/docs/google-cloud-policy-index + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: INFO +- id: terraform.gcp.security.gcp-compute-os-login.gcp-compute-os-login + patterns: + - pattern: resource + - pattern-inside: | + resource "google_compute_instance" "..." { + ... + metadata = { + enable-oslogin = false + } + ... + } + message: >- + Ensure that no instance in the project overrides the project setting for enabling OSLogin (OSLogin + needs to be enabled in project metadata for all instances) + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - gcp + references: + - https://docs.bridgecrew.io/docs/google-cloud-policy-index + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.gcp.security.gcp-compute-project-os-login.gcp-compute-project-os-login + patterns: + - pattern: resource + - pattern-inside: | + resource "google_compute_project_metadata" "..." { + ... + } + - pattern-not-inside: | + resource "google_compute_project_metadata" "..." { + ... + metadata = { + enable-oslogin = "True" + } + ... + } + - pattern-not-inside: | + resource "google_compute_project_metadata" "..." { + ... + metadata = { + enable-oslogin = True + } + ... + } + message: >- + Ensure oslogin is enabled for a Project + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - gcp + references: + - https://docs.bridgecrew.io/docs/google-cloud-policy-index + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.gcp.security.gcp-compute-public-ip.gcp-compute-public-ip + patterns: + - pattern: resource + - pattern-inside: | + resource "google_compute_instance" "..." { + ... + network_interface { + ... + network = "default" + ... + } + ... + } + message: >- + Ensure that Compute instances do not have public IP addresses + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - gcp + references: + - https://docs.bridgecrew.io/docs/google-cloud-policy-index + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.gcp.security.gcp-compute-serial-ports.gcp-compute-serial-ports + patterns: + - pattern: resource + - pattern-inside: | + resource "google_compute_instance" "..." { + ... + metadata = { + serial-port-enable = true + } + ... + } + message: >- + Ensure 'Enable connecting to serial ports' is not enabled for VM Instance + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - gcp + references: + - https://docs.bridgecrew.io/docs/google-cloud-policy-index + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.gcp.security.gcp-compute-ssl-policy.gcp-compute-ssl-policy + patterns: + - pattern: resource + - pattern-either: + - pattern-inside: | + resource "google_compute_ssl_policy" "..." { + ... + profile = "MODERN" + ... + } + - pattern-inside: | + resource "google_compute_ssl_policy" "..." { + ... + profile = "CUSTOM" + custom_features = [..., "TLS_RSA_WITH_AES_256_GCM_SHA384", ...] + ... + } + - pattern-not-inside: | + resource "google_compute_ssl_policy" "..." { + ... + profile = "MODERN" + min_tls_version = "TLS_1_2" + ... + } + - pattern-not-inside: | + resource "google_compute_ssl_policy" "..." { + ... + profile = "CUSTOM" + custom_features = ["TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"] + ... + } + message: >- + Ensure no HTTPS or SSL proxy load balancers permit SSL policies with weak cipher suites + metadata: + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + cwe: + - 'CWE-326: Inadequate Encryption Strength' + category: security + technology: + - terraform + - gcp + references: + - https://docs.bridgecrew.io/docs/google-cloud-policy-index + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.gcp.security.gcp-compute-template-ip-forward.gcp-compute-template-ip-forward + patterns: + - pattern: resource + - pattern-inside: | + resource "google_compute_instance_template" "..." { + ... + can_ip_forward = true + ... + } + message: >- + Ensure that IP forwarding is not enabled on Instances. This lets the instance act as a traffic router + and + receive traffic not intended for it, which may route traffic through unintended passages. + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + references: + - https://www.trendmicro.com/cloudoneconformity/knowledge-base/gcp/ComputeEngine/disable-ip-forwarding.html + technology: + - terraform + - gcp + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: INFO +- id: terraform.gcp.security.gcp-compute-template-public-ip.gcp-compute-template-public-ip + patterns: + - pattern: resource + - pattern-inside: | + resource "google_compute_instance_template" "..." { + ... + network_interface { + ... + network = "default" + ... + } + ... + } + message: >- + Ensure that Compute instances do not have public IP addresses + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - gcp + references: + - https://docs.bridgecrew.io/docs/google-cloud-policy-index + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.gcp.security.gcp-dataflow-job-encrypted-with-cmk.gcp-dataflow-job-encrypted-with-cmk + patterns: + - pattern: | + resource "google_dataflow_job" $ANYTHING { + ... + } + - pattern-not-inside: | + resource "google_dataflow_job" $ANYTHING { + ... + kms_key_name = ... + ... + } + message: >- + Ensure data flow jobs are encrypted with Customer Supplied Encryption Keys (CSEK) + metadata: + category: security + technology: + - terraform + - gcp + owasp: + - A03:2017 - Sensitive Data Exposure + cwe: + - 'CWE-320: CWE CATEGORY: Key Management Errors' + references: + - https://docs.bridgecrew.io/docs/google-cloud-policy-index + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.gcp.security.gcp-dataflow-private-job.gcp-dataflow-private-job + patterns: + - pattern: resource + - pattern-inside: | + resource "google_dataflow_job" "..." { + ... + } + - pattern-not-inside: | + resource "google_dataflow_job" "..." { + ... + ip_configuration = "WORKER_IP_PRIVATE" + ... + } + message: >- + Ensure Dataflow jobs are private + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - gcp + references: + - https://docs.bridgecrew.io/docs/google-cloud-policy-index + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.gcp.security.gcp-datafusion-private-instance.gcp-datafusion-private-instance + patterns: + - pattern: resource + - pattern-inside: | + resource "google_data_fusion_instance" "..." { + ... + } + - pattern-not-inside: | + resource "google_data_fusion_instance" "..." { + ... + private_instance = true + ... + } + message: >- + Ensure Data fusion instances are private + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - gcp + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.gcp.security.gcp-datafusion-stack-driver-logging.gcp-datafusion-stack-driver-logging + patterns: + - pattern-inside: | + resource "google_data_fusion_instance" $ANYTHING { + ... + } + - pattern-not-inside: | + resource "google_data_fusion_instance" $ANYTHING { + ... + enable_stackdriver_logging = true + ... + } + message: Ensure Datafusion has stack driver logging enabled. + languages: [hcl] + severity: WARNING + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + technology: + - terraform + - gcp + category: security + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW +- id: terraform.gcp.security.gcp-datafusion-stack-driver-monitoring.gcp-datafusion-stack-driver-monitoring + patterns: + - pattern-inside: | + resource "google_data_fusion_instance" $ANYTHING { + ... + } + - pattern-not-inside: | + resource "google_data_fusion_instance" $ANYTHING { + ... + enable_stackdriver_monitoring = true + ... + } + message: Ensure Datafusion has stack driver monitoring enabled. + languages: [hcl] + severity: WARNING + metadata: + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + cwe: + - 'CWE-326: Inadequate Encryption Strength' + technology: + - terraform + - gcp + category: security + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW +- id: terraform.gcp.security.gcp-dataproc-cluster-encrypted-with-cmk.gcp-dataproc-cluster-encrypted-with-cmk + patterns: + - pattern: | + resource "google_dataproc_cluster" $ANYTHING { + ... + } + - pattern-not-inside: | + resource "google_dataproc_cluster" $ANYTHING { + ... + cluster_config { + encryption_config { + ... + kms_key_name = ... + ... + } + } + ... + } + message: >- + Ensure Dataproc cluster is encrypted with Customer Supplied Encryption Keys (CSEK) + metadata: + category: security + technology: + - terraform + - gcp + owasp: + - A03:2017 - Sensitive Data Exposure + cwe: + - 'CWE-320: CWE CATEGORY: Key Management Errors' + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.gcp.security.gcp-dataproc-cluster-public-ip.gcp-dataproc-cluster-public-ip + patterns: + - pattern: resource + - pattern-inside: | + resource "google_dataproc_cluster" "..." { + ... + } + - pattern-not-inside: | + resource "google_dataproc_cluster" "..." { + ... + cluster_config { + gce_cluster_config { + ... + internal_ip_only = true + ... + } + ... + } + } + message: >- + Ensure Dataproc Clusters do not have public IPs + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - gcp + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.gcp.security.gcp-dataproc-private-cluster-iam-binding.gcp-dataproc-private-cluster-iam-binding + patterns: + - pattern: resource + - pattern-either: + - pattern-inside: | + resource "google_dataproc_cluster_iam_binding" "..." { + ... + members = [ ..., "allAuthenticatedUsers", ...] + ... + } + - pattern-inside: | + resource "google_dataproc_cluster_iam_binding" "..." { + ... + members = [ ..., "allUsers", ...] + ... + } + message: >- + Ensure that Dataproc clusters are not anonymously or publicly accessible + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - gcp + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.gcp.security.gcp-dataproc-private-cluster-iam-member.gcp-dataproc-private-cluster-iam-member + patterns: + - pattern: resource + - pattern-either: + - pattern-inside: | + resource "google_dataproc_cluster_iam_member" "..." { + ... + member = "allUsers" + ... + } + - pattern-inside: | + resource "google_dataproc_cluster_iam_member" "..." { + ... + member = "allAuthenticatedUsers" + ... + } + message: >- + Ensure that Dataproc clusters are not anonymously or publicly accessible + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - gcp + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.gcp.security.gcp-dns-key-specs-rsasha1.gcp-dns-key-specs-rsasha1 + patterns: + - pattern: resource + - pattern-inside: | + resource "google_dns_managed_zone" "..." { + ... + dnssec_config { + ... + default_key_specs { + ... + algorithm = "rsasha1" + key_type = "zoneSigning" + ... + } + ... + } + ... + } + - pattern-inside: | + resource "google_dns_managed_zone" "..." { + ... + dnssec_config { + ... + default_key_specs { + ... + algorithm = "rsasha1" + key_type = "keySigning" + ... + } + ... + } + ... + } + message: >- + Ensure that RSASHA1 is not used for the zone-signing and key-signing keys in Cloud DNS DNSSEC + metadata: + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + cwe: + - 'CWE-326: Inadequate Encryption Strength' + category: security + technology: + - terraform + - gcp + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - vuln + likelihood: LOW + impact: MEDIUM + confidence: MEDIUM + languages: [hcl] + severity: WARNING +- id: terraform.gcp.security.gcp-folder-impersonation-roles-iam-binding.gcp-folder-impersonation-roles-iam-binding + patterns: + - pattern: resource + - pattern-inside: | + resource "google_folder_iam_binding" "..." { + ... + role = "roles/editor" + members = [ ... ] + ... + } + message: >- + Ensure no roles that enable to impersonate and manage all service accounts are used at a folder level + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - gcp + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.gcp.security.gcp-folder-impersonation-roles-iam-member.gcp-folder-impersonation-roles-iam-member + patterns: + - pattern: resource + - pattern-inside: | + resource "google_folder_iam_member" "..." { + ... + role = "roles/editor" + member = ... + ... + } + message: >- + Ensure no roles that enable to impersonate and manage all service accounts are used at a folder level + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - gcp + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.gcp.security.gcp-folder-member-default-service-account-iam-binding.gcp-folder-member-default-service-account-iam-binding + patterns: + - pattern: resource + - pattern-inside: | + resource "google_folder_iam_binding" "..." { + ... + members = [..., $MEMBER, ...] + ... + } + - metavariable-regex: + metavariable: $MEMBER + regex: ((.*)-compute@appspot.gserviceaccount.com) + message: >- + Ensure Default Service account is not used at a folder level + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - gcp + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.gcp.security.gcp-folder-member-default-service-account-iam-member.gcp-folder-member-default-service-account-iam-member + patterns: + - pattern: resource + - pattern-inside: | + resource "google_folder_iam_member" "..." { + ... + member = $MEMBER + ... + } + - metavariable-regex: + metavariable: $MEMBER + regex: ((.*)-compute@developer.gserviceaccount.com) + message: >- + Ensure Default Service account is not used at a folder level + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - gcp + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.gcp.security.gcp-gke-basic-auth.gcp-gke-basic-auth + patterns: + - pattern: resource + - pattern-inside: | + resource "google_container_cluster" "..." { + ... + } + - pattern-not-inside: | + resource "google_container_cluster" "..." { + ... + master_auth { + client_certificate_config { + ... + } + } + ... + } + - pattern-not-inside: | + resource "google_container_cluster" "..." { + ... + master_auth { + ... + username = "" + password = "" + ... + } + ... + } + message: >- + Ensure GKE basic auth is disabled + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - gcp + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.gcp.security.gcp-gke-client-certificate-disabled.gcp-gke-client-certificate-disabled + patterns: + - pattern: resource + - pattern-inside: | + resource "google_container_cluster" "..." { + ... + } + - pattern-not-inside: | + resource "google_container_cluster" "..." { + ... + master_auth { + ... + client_certificate_config { + ... + issue_client_certificate = false + ... + } + ... + } + ... + } + message: >- + Ensure client certificate authentication to Kubernetes Engine Clusters is disabled + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - gcp + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.gcp.security.gcp-gke-cluster-logging.gcp-gke-cluster-logging + patterns: + - pattern: | + resource "google_container_cluster" $ANYTHING { + ... + logging_service = "none" + ... + } + message: Ensure logging is set to Enabled on Kubernetes Engine Clusters + languages: [hcl] + severity: WARNING + metadata: + owasp: + - A03:2017 - Sensitive Data Exposure + cwe: + - 'CWE-320: CWE CATEGORY: Key Management Errors' + technology: + - terraform + - gcp + category: security + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW +- id: terraform.gcp.security.gcp-gke-enabled-vpc-flow-logs.gcp-gke-enabled-vpc-flow-logs + patterns: + - pattern-inside: | + resource "google_container_cluster" $ANYTHING { + ... + } + - pattern-not-inside: | + resource "google_container_cluster" $ANYTHING { + ... + enable_intranode_visibility = true + ... + } + message: Enable VPC Flow Logs and Intranode Visibility + languages: [hcl] + severity: WARNING + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + technology: + - terraform + - gcp + category: security + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW +- id: terraform.gcp.security.gcp-gke-ensure-integrity-monitoring.gcp-gke-ensure-integrity-monitoring + patterns: + - pattern-inside: | + resource "google_container_cluster" $ANYTHING { + ... + node_config { + ... + shielded_instance_config { + enable_integrity_monitoring = false + } + ... + } + ... + } + message: Ensure Integrity Monitoring for Shielded GKE Nodes is Enabled + languages: [hcl] + severity: WARNING + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + technology: + - terraform + - gcp + category: security + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW +- id: terraform.gcp.security.gcp-gke-kubernetes-rbac-google-groups.gcp-gke-kubernetes-rbac-google-groups + patterns: + - pattern: resource + - pattern-inside: | + resource "google_container_cluster" "..." { + ... + } + - pattern-not-inside: | + resource "google_container_cluster" "..." { + ... + authenticator_groups_config { + ... + security_group = "..." + ... + } + ... + } + message: >- + Manage Kubernetes RBAC users with Google Groups for GKE + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - gcp + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.gcp.security.gcp-gke-legacy-auth-enabled.gcp-gke-legacy-auth-enabled + patterns: + - pattern: resource + - pattern-inside: | + resource "google_container_cluster" "..." { + ... + enable_legacy_abac = true + ... + } + message: >- + Ensure Legacy Authorization is set to Disabled on Kubernetes Engine Clusters + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - gcp + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.gcp.security.gcp-gke-legacy-instance-metadata-disabled.gcp-gke-legacy-instance-metadata-disabled + patterns: + - pattern: resource + - pattern-inside: | + resource "google_container_cluster" "..." { + ... + } + - pattern-not-inside: | + resource "google_container_cluster" "..." { + ... + min_master_version = 1.12 + ... + } + - pattern-not-inside: | + resource "google_container_cluster" "..." { + ... + min_master_version = 1.13 + ... + } + message: >- + Ensure legacy Compute Engine instance metadata APIs are Disabled + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - gcp + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.gcp.security.gcp-gke-master-authz-networks-enabled.gcp-gke-master-authz-networks-enabled + patterns: + - pattern: resource + - pattern-inside: | + resource "google_container_cluster" "..." { + ... + } + - pattern-not-inside: | + resource "google_container_cluster" "..." { + ... + master_authorized_networks_config { + ... + } + ... + } + message: >- + Ensure master authorized networks is set to enabled in GKE clusters + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - gcp + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.gcp.security.gcp-gke-monitoring-enabled.gcp-gke-monitoring-enabled + patterns: + - pattern-inside: | + resource "google_container_cluster" $ANYTHING { + ... + monitoring_service = "none" + ... + } + message: Ensure monitoring is set to Enabled on Kubernetes Engine Clusters + languages: [hcl] + severity: WARNING + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + technology: + - terraform + - gcp + category: security + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW +- id: terraform.gcp.security.gcp-gke-network-policy-enabled.gcp-gke-network-policy-enabled + patterns: + - pattern: resource + - pattern-inside: | + resource "google_container_cluster" "..." { + ... + network_policy { + ... + enabled = false + ... + } + ... + } + - pattern-not-inside: | + resource "google_container_cluster" "..." { + ... + datapath_provider = "ADVANCED_DATAPATH" + network_policy { + ... + enabled = false + ... + } + ... + } + message: >- + Ensure Network Policy is enabled on Kubernetes Engine Clusters + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - gcp + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.gcp.security.gcp-gke-nodepool-integrity-monitoring.gcp-gke-nodepool-integrity-monitoring + patterns: + - pattern-inside: | + resource "google_container_node_pool" $ANYTHING { + ... + node_config { + ... + shielded_instance_config { + enable_integrity_monitoring = false + } + ... + } + ... + } + message: Ensure Integrity Monitoring for Shielded GKE Nodes is Enabled + languages: [hcl] + severity: WARNING + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + technology: + - terraform + - gcp + category: security + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW +- id: terraform.gcp.security.gcp-gke-pod-security-policy-enabled.gcp-gke-pod-security-policy-enabled + patterns: + - pattern: resource + - pattern-inside: | + resource "google_container_cluster" "..." { + ... + } + - pattern-not-inside: | + resource "google_container_cluster" "..." { + ... + pod_security_policy_config { + ... + enabled = true + ... + } + ... + } + message: >- + Ensure PodSecurityPolicy controller is enabled on the Kubernetes Engine Clusters + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - gcp + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.gcp.security.gcp-gke-private-cluster-config.gcp-gke-private-cluster-config + patterns: + - pattern: resource + - pattern-inside: | + resource "google_container_cluster" "..." { + ... + } + - pattern-not-inside: | + resource "google_container_cluster" "..." { + ... + private_cluster_config { + ... + } + ... + } + message: >- + Ensure Kubernetes Cluster is created with Private cluster enabled + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - gcp + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.gcp.security.gcp-gke-public-control-plane.gcp-gke-public-control-plane + patterns: + - pattern: resource + - pattern-inside: | + resource "google_container_cluster" "..." { + ... + } + - pattern-not-inside: | + resource "google_container_cluster" "..." { + ... + master_authorized_networks_config { + ... + cidr_blocks { + ... + } + ... + } + ... + } + message: >- + Ensure GKE Control Plane is not public + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - gcp + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.gcp.security.gcp-gke-secure-boot-for-shielded-nodes.gcp-gke-secure-boot-for-shielded-nodes + patterns: + - pattern: resource + - pattern-inside: | + resource "google_container_cluster" "..." { + ... + } + - pattern-not-inside: | + resource "google_container_cluster" "..." { + ... + shielded_instance_config { + ... + enable_secure_boot = true + ... + } + ... + } + message: >- + Ensure Secure Boot for Shielded GKE Nodes is Enabled + metadata: + category: best-practice + technology: + - terraform + - gcp + languages: [hcl] + severity: WARNING +- id: terraform.gcp.security.gcp-insecure-load-balancer-tls-version.gcp-insecure-load-balancer-tls-version + patterns: + - pattern: | + resource "google_compute_ssl_policy" $ANYTHING { + ... + min_tls_version = "..." + ... + } + - pattern-not: | + resource "google_compute_ssl_policy" $ANYTHING { + ... + min_tls_version = "TLS_1_2" + ... + } + message: >- + Detected GCP Load Balancer to be using an insecure version of TLS. To fix this set your "min_tls_version" + to "TLS_1_2" + languages: + - terraform + severity: WARNING + metadata: + cwe: + - 'CWE-326: Inadequate Encryption Strength' + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + technology: + - gcp + - terraform + category: security + references: + - https://docs.bridgecrew.io/docs/google-cloud-policy-index + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW +- id: terraform.gcp.security.gcp-kms-prevent-destroy.gcp-kms-prevent-destroy + patterns: + - pattern: resource + - pattern-inside: | + resource "google_kms_crypto_key" "..." { + ... + } + - pattern-not-inside: | + resource "google_kms_crypto_key" "..." { + ... + lifecycle { + prevent_destroy = true + } + ... + } + message: >- + Ensure KMS keys are protected from deletion + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - gcp + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.gcp.security.gcp-memory-store-for-redis-auth-enabled.gcp-memory-store-for-redis-auth-enabled + patterns: + - pattern: resource + - pattern-inside: | + resource "google_redis_instance" "..." { + ... + } + - pattern-not-inside: | + resource "google_redis_instance" "..." { + ... + auth_enabled = true + ... + } + message: >- + Ensure Memorystore for Redis has AUTH enabled + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - gcp + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.gcp.security.gcp-memory-store-for-redis-intransit-encryption.gcp-memory-store-for-redis-intransit-encryption + patterns: + - pattern: | + resource "google_redis_instance" $ANYTHING { + ... + } + - pattern-not-inside: | + resource "google_redis_instance" $ANYTHING { + ... + transit_encryption_mode = "SERVER_AUTHENTICATION" + ... + } + message: Ensure Memorystore for Redis uses intransit encryption + languages: [hcl] + severity: WARNING + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + technology: + - terraform + - gcp + category: security + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW +- id: terraform.gcp.security.gcp-org-impersonation-roles-iam-binding.gcp-org-impersonation-roles-iam-binding + patterns: + - pattern: resource + - pattern-inside: | + resource "google_organization_iam_binding" "..." { + ... + role = "roles/editor" + members = [ ... ] + ... + } + message: >- + Ensure no roles that enable to impersonate and manage all service accounts are used at an organization + level + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - gcp + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.gcp.security.gcp-org-impersonation-roles-iam-member.gcp-org-impersonation-roles-iam-member + patterns: + - pattern: resource + - pattern-inside: | + resource "google_organization_iam_member" "..." { + ... + role = "roles/editor" + member = ... + ... + } + message: >- + Ensure no roles that enable to impersonate and manage all service accounts are used at an organization + level + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - gcp + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.gcp.security.gcp-org-member-default-service-account-iam-binding.gcp-org-member-default-service-account-iam-binding + patterns: + - pattern: resource + - pattern-inside: | + resource "google_organization_iam_binding" "..." { + ... + members = [..., $MEMBER, ...] + ... + } + - metavariable-regex: + metavariable: $MEMBER + regex: ((.*)-compute@developer.gserviceaccount.com) + message: >- + Ensure default service account is not used at an organization level + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - gcp + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.gcp.security.gcp-org-member-default-service-account-iam-member.gcp-org-member-default-service-account-iam-member + patterns: + - pattern: resource + - pattern-inside: | + resource "google_organization_iam_member" "..." { + ... + member = $MEMBER + ... + } + - metavariable-regex: + metavariable: $MEMBER + regex: ((.*)-compute@developer.gserviceaccount.com) + message: >- + Ensure default service account is not used at an organization level + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - gcp + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.gcp.security.gcp-project-default-network.gcp-project-default-network + patterns: + - pattern: resource + - pattern-inside: | + resource "google_project" "..." { + ... + } + - pattern-not-inside: | + resource "google_project" "..." { + ... + auto_create_network = false + ... + } + message: >- + Ensure that the default network does not exist in a project. Set + auto_create_network to `false`. + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - gcp + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.gcp.security.gcp-project-member-default-service-account-iam-binding.gcp-project-member-default-service-account-iam-binding + patterns: + - pattern: resource + - pattern-inside: | + resource "google_project_iam_binding" "..." { + ... + members = [..., $MEMBER, ...] + ... + } + - metavariable-regex: + metavariable: $MEMBER + regex: ((.*)-compute@developer.gserviceaccount.com) + message: >- + Ensure Default Service account is not used at a project level + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - gcp + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.gcp.security.gcp-project-member-default-service-account-iam-member.gcp-project-member-default-service-account-iam-member + patterns: + - pattern: resource + - pattern-inside: | + resource "google_project_iam_member" "..." { + ... + member = $MEMBER + ... + } + - metavariable-regex: + metavariable: $MEMBER + regex: ((.*)-compute@developer.gserviceaccount.com) + message: >- + Ensure Default Service account is not used at a project level + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - gcp + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.gcp.security.gcp-project-service-account-user-iam-binding.gcp-project-service-account-user-iam-binding + patterns: + - pattern: resource + - pattern-either: + - pattern-inside: | + resource "google_project_iam_binding" "..." { + ... + role = "roles/iam.serviceAccountTokenCreator" + ... + } + - pattern-inside: | + resource "google_project_iam_binding" "..." { + ... + role = "roles/iam.serviceAccountUser" + ... + } + message: >- + Ensure that IAM users are not assigned the Service Account User or Service Account Token Creator roles + at project level + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - gcp + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.gcp.security.gcp-project-service-account-user-iam-member.gcp-project-service-account-user-iam-member + patterns: + - pattern: resource + - pattern-either: + - pattern-inside: | + resource "google_project_iam_member" "..." { + ... + role = "roles/iam.serviceAccountTokenCreator" + ... + } + - pattern-inside: | + resource "google_project_iam_member" "..." { + ... + role = "roles/iam.serviceAccountUser" + ... + } + message: >- + Ensure that IAM users are not assigned the Service Account User or Service Account Token Creator roles + at project level + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - gcp + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.gcp.security.gcp-pubsub-encrypted-with-cmk.gcp-pubsub-encrypted-with-cmk + patterns: + - pattern: | + resource "google_pubsub_topic" $ANYTHING { + ... + } + - pattern-not-inside: | + resource "google_pubsub_topic" $ANYTHING { + ... + kms_key_name = ... + ... + } + message: >- + Ensure PubSub Topics are encrypted with Customer Supplied Encryption Keys (CSEK) + metadata: + category: security + technology: + - terraform + - gcp + owasp: + - A03:2017 - Sensitive Data Exposure + cwe: + - 'CWE-320: CWE CATEGORY: Key Management Errors' + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.gcp.security.gcp-pubsub-private-topic-iam-binding.gcp-pubsub-private-topic-iam-binding + patterns: + - pattern: resource + - pattern-either: + - pattern-inside: | + resource "google_pubsub_topic_iam_binding" "..." { + ... + members = [ ..., "allAuthenticatedUsers", ...] + ... + } + - pattern-inside: | + resource "google_pubsub_topic_iam_binding" "..." { + ... + members = [ ..., "allUsers", ...] + ... + } + message: >- + Ensure that Pub/Sub Topics are not anonymously or publicly accessible + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - gcp + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.gcp.security.gcp-pubsub-private-topic-iam-member.gcp-pubsub-private-topic-iam-member + patterns: + - pattern: resource + - pattern-either: + - pattern-inside: | + resource "google_pubsub_topic_iam_member" "..." { + ... + member = "allUsers" + ... + } + - pattern-inside: | + resource "google_pubsub_topic_iam_member" "..." { + ... + member = "allAuthenticatedUsers" + ... + } + message: >- + Ensure that Pub/Sub Topics are not anonymously or publicly accessible + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - gcp + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.gcp.security.gcp-run-private-service-iam-binding.gcp-run-private-service-iam-binding + patterns: + - pattern: resource + - pattern-either: + - pattern-inside: | + resource "google_cloud_run_service_iam_binding" "..." { + ... + members = [ ..., "allAuthenticatedUsers", ...] + ... + } + - pattern-inside: | + resource "google_cloud_run_service_iam_binding" "..." { + ... + members = [ ..., "allUsers", ...] + ... + } + message: >- + Ensure that GCP Cloud Run services are not anonymously or publicly accessible + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - gcp + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.gcp.security.gcp-run-private-service-iam-member.gcp-run-private-service-iam-member + patterns: + - pattern: resource + - pattern-either: + - pattern-inside: | + resource "google_cloud_run_service_iam_member" "..." { + ... + member = "allAuthenticatedUsers" + ... + } + - pattern-inside: | + resource "google_cloud_run_service_iam_member" "..." { + ... + member = "allUsers" + ... + } + message: >- + Ensure that GCP Cloud Run services are not anonymously or publicly accessible + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - gcp + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.gcp.security.gcp-spanner-database-encrypted-with-cmk.gcp-spanner-database-encrypted-with-cmk + patterns: + - pattern: | + resource "google_spanner_database" $ANYTHING { + ... + } + - pattern-not-inside: | + resource "google_spanner_database" $ANYTHING { + ... + encryption_config { + ... + kms_key_name = ... + ... + } + ... + } + message: >- + Ensure Spanner Database is encrypted with Customer Supplied Encryption Keys (CSEK) + metadata: + category: security + technology: + - terraform + - gcp + owasp: + - A03:2017 - Sensitive Data Exposure + cwe: + - 'CWE-320: CWE CATEGORY: Key Management Errors' + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.gcp.security.gcp-sql-database-require-ssl.gcp-sql-database-require-ssl + patterns: + - pattern: resource + - pattern-inside: | + resource "google_sql_database_instance" "..." { + ... + } + - pattern-not-inside: | + resource "google_sql_database_instance" "..." { + ... + ip_configuration { + ... + require_ssl = true + ... + } + ... + } + message: >- + Ensure all Cloud SQL database instance requires all incoming connections to use SSL + metadata: + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + cwe: + - 'CWE-326: Inadequate Encryption Strength' + category: security + technology: + - terraform + - gcp + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - vuln + likelihood: LOW + impact: MEDIUM + confidence: MEDIUM + languages: [hcl] + severity: WARNING +- id: terraform.gcp.security.gcp-sql-public-database.gcp-sql-public-database + patterns: + - pattern: resource + - pattern-either: + - pattern-inside: | + resource "google_sql_database_instance" "..." { + ... + ip_configuration { + ... + authorized_networks { + ... + value = "0.0.0.0/0" + ... + } + ... + } + ... + } + - pattern-inside: | + resource "google_sql_database_instance" "..." { + ... + ip_configuration { + ... + dynamic "authorized_networks" { + ... + content { + ... + value = "0.0.0.0/0" + ... + } + ... + } + ... + } + ... + } + message: >- + Ensure that Cloud SQL database Instances are not open to the world + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - gcp + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + languages: [hcl] + severity: WARNING +- id: terraform.gcp.security.gcp-sqlserver-no-public-ip.gcp-sqlserver-no-public-ip + patterns: + - pattern: resource + - pattern-inside: | + resource "google_sql_database_instance" "..." { + ... + ip_configuration { + ... + ipv4_enabled = true + ... + } + ... + } + message: >- + Ensure Cloud SQL database does not have public IP + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - gcp + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.gcp.security.gcp-storage-bucket-not-public-iam-binding.gcp-storage-bucket-not-public-iam-binding + patterns: + - pattern: resource + - pattern-inside: | + resource "google_storage_bucket_iam_binding" "..." { + ... + members = [ ..., "allAuthenticatedUsers", ...] + ... + } + message: >- + Ensure that Container Registry repositories are not anonymously or publicly accessible + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - gcp + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.gcp.security.gcp-storage-bucket-not-public-iam-member.gcp-storage-bucket-not-public-iam-member + patterns: + - pattern: resource + - pattern-inside: | + resource "google_storage_bucket_iam_member" "..." { + ... + member = "allUsers" + ... + } + message: >- + Ensure that Container Registry repositories are not anonymously or publicly accessible + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - gcp + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.gcp.security.gcp-storage-bucket-uniform-access.gcp-storage-bucket-uniform-access + patterns: + - pattern: resource + - pattern-inside: | + resource "google_storage_bucket" "..." { + ... + } + - pattern-not-inside: | + resource "google_storage_bucket" "..." { + ... + uniform_bucket_level_access = true + ... + } + message: >- + Ensure that Cloud Storage buckets have uniform bucket-level access enabled + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - gcp + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.gcp.security.gcp-sub-network-logging-enabled.gcp-sub-network-logging-enabled + patterns: + - pattern: | + resource "google_compute_subnetwork" $ANYTHING { + ... + } + - pattern-not-inside: | + resource "google_compute_subnetwork" $ANYTHING { + ... + log_config { + ... + } + ... + } + message: Ensure that VPC Flow Logs is enabled for every subnet in a VPC Network + languages: [hcl] + severity: WARNING + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + technology: + - terraform + - gcp + category: security + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW +- id: terraform.gcp.security.gcp-sub-network-private-google-enabled.gcp-sub-network-private-google-enabled + patterns: + - pattern: resource + - pattern-inside: | + resource "google_compute_subnetwork" "..." { + ... + } + - pattern-not-inside: | + resource "google_compute_subnetwork" "..." { + ... + private_ip_google_access = true + ... + } + message: >- + Ensure that private_ip_google_access is enabled for Subnet + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - gcp + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.gcp.security.gcp-vertexai-dataset-encrypted-with-cmk.gcp-vertexai-dataset-encrypted-with-cmk + patterns: + - pattern: | + resource "google_vertex_ai_dataset" $ANYTHING { + ... + } + - pattern-not-inside: | + resource "google_vertex_ai_dataset" $ANYTHING { + ... + encryption_spec { + ... + kms_key_name = ... + ... + } + ... + } + message: >- + Ensure Vertex AI datasets uses a CMK (Customer Manager Key) + metadata: + category: security + technology: + - terraform + - gcp + owasp: + - A03:2017 - Sensitive Data Exposure + cwe: + - 'CWE-320: CWE CATEGORY: Key Management Errors' + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.gcp.security.gcp-vertexai-metadata-store-encrypted-with-cmk.gcp-vertexai-metadata-store-encrypted-with-cmk + patterns: + - pattern: | + resource "google_vertex_ai_metadata_store" $ANYTHING { + ... + } + - pattern-not-inside: | + resource "google_vertex_ai_metadata_store" $ANYTHING { + ... + encryption_spec { + ... + kms_key_name = ... + ... + } + ... + } + message: >- + Ensure Vertex AI Metadata Store uses a CMK (Customer Manager Key) + metadata: + category: security + technology: + - terraform + - gcp + owasp: + - A03:2017 - Sensitive Data Exposure + cwe: + - 'CWE-320: CWE CATEGORY: Key Management Errors' + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.gcp.security.gcp-vertexai-private-instance.gcp-vertexai-private-instance + patterns: + - pattern: resource + - pattern-inside: | + resource "google_notebooks_instance" "..." { + ... + } + - pattern-not-inside: | + resource "google_notebooks_instance" "..." { + ... + no_public_ip = true + ... + } + message: >- + Ensure Vertex AI instances are private + metadata: + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - gcp + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.lang.security.ec2-imdsv1-optional.ec2-imdsv1-optional + languages: + - hcl + message: >- + AWS EC2 Instance allowing use of the IMDSv1 + metadata: + cwe: + - 'CWE-918: Server-Side Request Forgery (SSRF)' + references: + - https://aws.amazon.com/blogs/security/defense-in-depth-open-firewalls-reverse-proxies-ssrf-vulnerabilities-ec2-instance-metadata-service + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance#metadata-options + category: security + technology: + - terraform + - aws + owasp: + - A10:2021 - Server-Side Request Forgery (SSRF) + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: LOW + impact: MEDIUM + confidence: MEDIUM + pattern-either: + # Legacy rule for backwards compatibility + - patterns: + - pattern: http_tokens = "optional" + - pattern-inside: | + metadata_options { ... } + - patterns: + - pattern: | + resource "aws_instance" "$NAME" { + ... + } + - pattern-not: | + resource "aws_instance" "$NAME" { + ... + metadata_options { + ... + http_tokens = "required" + ... + } + ... + } + # Don't match previous legacy rule + - pattern-not: | + resource "aws_instance" "$NAME" { + ... + metadata_options { + ... + http_tokens = "optional" + ... + } + ... + } + - pattern-not: | + resource "aws_instance" "$NAME" { + ... + metadata_options { + ... + http_endpoint = "disabled" + ... + } + ... + } + severity: ERROR +- id: terraform.lang.security.ecr-image-scan-on-push.ecr-image-scan-on-push + patterns: + - pattern: resource + - pattern-not-inside: | + resource "aws_ecr_repository" "..." { + ... + image_scanning_configuration { + ... + scan_on_push=true + ... + } + ... + } + - pattern-inside: | + resource "aws_ecr_repository" "..." { + ... + } + languages: + - hcl + message: >- + The ECR Repository isn't configured to scan images on push + severity: WARNING + metadata: + cwe: + - 'CWE-1104: Use of Unmaintained Third Party Components' + category: security + technology: + - terraform + - aws + owasp: + - A06:2021 - Vulnerable and Outdated Components + references: + - https://owasp.org/Top10/A06_2021-Vulnerable_and_Outdated_Components + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW +- id: terraform.lang.security.eks-insufficient-control-plane-logging.eks-insufficient-control-plane-logging + patterns: + - pattern: | + name = ... + - pattern-inside: | + resource "aws_eks_cluster" "..." { + ... + } + - pattern-not-inside: | + resource "aws_eks_cluster" "..." { + ... + enabled_cluster_log_types = [..., "api", ..., "audit", ...] + ... + } + - pattern-not-inside: | + resource "aws_eks_cluster" "..." { + ... + enabled_cluster_log_types = [..., "audit", ..., "api", ...] + ... + } + languages: + - hcl + message: Missing EKS control plane logging. It is recommended to enable at least + Kubernetes API server component logs ("api") and audit logs ("audit") of + the EKS control plane through the enabled_cluster_log_types attribute. + severity: WARNING + metadata: + references: + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_cluster#enabling-control-plane-logging + - https://docs.aws.amazon.com/eks/latest/userguide/control-plane-logs.html + category: security + cwe: + - "CWE-778: Insufficient Logging" + technology: + - terraform + - aws + owasp: + - A10:2017 - Insufficient Logging & Monitoring + - A09:2021 - Security Logging and Monitoring Failures + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + license: Commons Clause License Condition v1.0[LGPL-2.1-only] +- id: terraform.lang.security.eks-public-endpoint-enabled.eks-public-endpoint-enabled + patterns: + - pattern: | + resource + - pattern-inside: | + resource "aws_eks_cluster" "..." {...} + - pattern-not-inside: | + resource "aws_eks_cluster" "..."{ + ... + vpc_config{ + ... + endpoint_public_access = false + ... + } + ... + } + languages: + - hcl + message: >- + The vpc_config resource inside the eks cluster has not explicitly disabled public endpoint access + severity: WARNING + metadata: + category: security + cwe: + - 'CWE-200: Exposure of Sensitive Information to an Unauthorized Actor' + technology: + - terraform + - aws + owasp: + - A01:2021 - Broken Access Control + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW +- id: terraform.lang.security.elastic-search-encryption-at-rest.elastic-search-encryption-at-rest + patterns: + - pattern: | + resource + - pattern-not-inside: | + resource "aws_elasticsearch_domain" "..."{ + ... + encrypt_at_rest{ + ... + enabled = true + ... + } + ... + } + - pattern-inside: | + resource "aws_elasticsearch_domain" "..." {...} + languages: + - hcl + message: >- + Encryption at rest is not enabled for the elastic search domain resource + severity: WARNING + metadata: + category: security + cwe: + - 'CWE-311: Missing Encryption of Sensitive Data' + technology: + - terraform + - aws + owasp: + - A03:2017 - Sensitive Data Exposure + - A04:2021 - Insecure Design + references: + - https://owasp.org/Top10/A04_2021-Insecure_Design + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW +- id: terraform.lang.security.iam.no-iam-admin-privileges.no-iam-admin-privileges + pattern-either: + - patterns: + - pattern-inside: | + resource $TYPE "..." { + ... + policy = jsonencode({ + ... + Statement = [ + ... + ] + ... + }) + ... + } + - pattern-not-inside: | + resource $TYPE "..." { + ... + policy = jsonencode({ + ... + Statement = [ + ..., + {... Effect = "Deny" ...}, + ... + ] + ... + }) + ... + } + - patterns: + - pattern: | + {..., Action = "*", ...} + - pattern: | + {..., Resource = "*", ...} + - metavariable-pattern: + metavariable: $TYPE + pattern-either: + - pattern: | + "aws_iam_role_policy" + - pattern: | + "aws_iam_policy" + - pattern: | + "aws_iam_user_policy" + - pattern: | + "aws_iam_group_policy" + - patterns: + - pattern-inside: | + data aws_iam_policy_document "..." { + ... + statement { + ... + } + ... + } + - pattern-not-inside: | + data aws_iam_policy_document "..." { + ... + statement { + ... + effect = "Deny" + ... + } + ... + } + - patterns: + - pattern: | + {..., resources = ["*"], ...} + - pattern: | + {..., actions = ["*"], ...} + message: >- + IAM policies that allow full "*-*" admin privileges violates the principle of least privilege. + This allows an attacker to take full control over all AWS account resources. Instead, give each user + more fine-grained control with only the privileges they need. $TYPE + metadata: + references: + - https://github.com/bridgecrewio/checkov/blob/master/checkov/terraform/checks/data/aws/AdminPolicyDocument.py + category: security + cwe: + - 'CWE-269: Improper Privilege Management' + license: Commons Clause License Condition v1.0[LGPL-2.1-only] + technology: + - terraform + - aws + owasp: + - A04:2021 - Insecure Design + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.lang.security.iam.no-iam-creds-exposure.no-iam-creds-exposure + patterns: + - pattern-either: + - patterns: + - pattern-inside: | + resource $TYPE "..." { + ... + policy = jsonencode({ + ... + Statement = [ + ... + ] + ... + }) + ... + } + - pattern-not-inside: | + resource $TYPE "..." { + ... + policy = jsonencode({ + ... + Statement = [ + ..., + {... Effect = "Deny" ...}, + ... + ] + ... + }) + ... + } + - pattern: | + Action = $ACTION + - metavariable-pattern: + metavariable: $TYPE + pattern-either: + - pattern: | + "aws_iam_role_policy" + - pattern: | + "aws_iam_policy" + - pattern: | + "aws_iam_user_policy" + - pattern: | + "aws_iam_group_policy" + - patterns: + - pattern-inside: | + data aws_iam_policy_document "..." { + ... + statement { + ... + } + ... + } + - pattern-not-inside: | + data aws_iam_policy_document "..." { + ... + statement { + ... + effect = "Deny" + ... + } + ... + } + - pattern: | + actions = [..., $ACTION, ...] + - metavariable-pattern: + metavariable: $ACTION + pattern-either: + - pattern: | + "chime:CreateApiKey" + - pattern: | + "codepipeline:PollForJobs" + - pattern: | + "cognito-identity:GetOpenIdToken" + - pattern: | + "cognito-identity:GetOpenIdTokenForDeveloperEdentity" + - pattern: | + "cognito-identity:GetCredentialsForIdentity" + - pattern: | + "connect:GetFederationToken" + - pattern: | + "connect:GetFederationTokens" + - pattern: | + "ec2:GetPasswordData" + - pattern: | + "ecr:GetAuthorizationToken" + - pattern: | + "gamelift:RequestUploadCredentials" + - pattern: | + "iam:CreateAccessKey" + - pattern: | + "iam:CreateLoginProfile" + - pattern: | + "iam:CreateServiceSpecificCredential" + - pattern: | + "iam:ResetServiceSpecificCredential" + - pattern: | + "iam:UpdateAccessKey" + - pattern: | + "lightsail:GetInstanceAccessDetails" + - pattern: | + "lightsail:GetRelationalDatabaseMasterUserPassword" + - pattern: | + "rds-db:Connect" + - pattern: | + "redshift:GetClusterCredentials" + - pattern: | + "sso:GetRoleCredentials" + - pattern: | + "mediapackage:RotateChannelCredentials" + - pattern: | + "mediapackage:RotateIngestEndpointCredentials" + - pattern: | + "sts:AssumeRole" + - pattern: | + "sts:AssumeRoleWithSaml" + - pattern: | + "sts:AssumeRoleWithWebIdentity" + - pattern: | + "sts:GetFederationToken" + - pattern: | + "sts:GetSessionToken" + - pattern: | + "ec2:*" + - pattern: | + "codepipeline:*" + - pattern: | + "rds-db:*" + - pattern: | + "connect:*" + - pattern: | + "iam:*" + - pattern: | + "ecr:*" + - pattern: | + "sts:*" + - pattern: | + "chime:*" + - pattern: | + "mediapackage:*" + - pattern: | + "redshift:*" + - pattern: | + "gamelift:*" + - pattern: | + "cognito-identity:*" + - pattern: | + "lightsail:*" + - pattern: | + "sso:*" + message: >- + Ensure IAM policies don't allow credentials exposure. Credentials exposure actions return credentials + as part of the API response, and can possibly lead to leaking important credentials. Instead, + use another action that doesn't return sensitive data as part of the API response. + metadata: + references: + - https://cloudsplaining.readthedocs.io/en/latest/glossary/credentials-exposure/ + - https://github.com/bridgecrewio/checkov/blob/ca830e14745c2c8e1b941985f305abe985d7f1f9/checkov/terraform/checks/data/aws/IAMCredentialsExposure.py + category: security + cwe: + - 'CWE-200: Exposure of Sensitive Information to an Unauthorized Actor' + license: Commons Clause License Condition v1.0[LGPL-2.1-only] + technology: + - terraform + - aws + owasp: + - A01:2021 - Broken Access Control + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.lang.security.iam.no-iam-data-exfiltration.no-iam-data-exfiltration + patterns: + - pattern-either: + - patterns: + - pattern-inside: | + resource $TYPE "..." { + ... + policy = jsonencode({ + ... + Statement = [ + ..., + {... Resource = "*" ...}, + ... + ] + ... + }) + ... + } + - pattern-not-inside: | + resource $TYPE "..." { + ... + policy = jsonencode({ + ... + Statement = [ + ..., + {... Effect = "Deny" ...}, + ... + ] + ... + }) + ... + } + - pattern: | + Action = $ACTION + - metavariable-pattern: + metavariable: $TYPE + pattern-either: + - pattern: | + "aws_iam_role_policy" + - pattern: | + "aws_iam_policy" + - pattern: | + "aws_iam_user_policy" + - pattern: | + "aws_iam_group_policy" + - patterns: + - pattern-inside: | + data aws_iam_policy_document "..." { + ... + statement { + ... + resources = ["*"] + ... + } + ... + } + - pattern-not-inside: | + data aws_iam_policy_document "..." { + ... + statement { + ... + effect = "Deny" + ... + } + ... + } + - pattern: | + actions = [..., $ACTION, ...] + - metavariable-pattern: + metavariable: $ACTION + pattern-either: + - pattern: | + "s3:GetObject" + - pattern: | + "ssm:GetParameter*" + - pattern: | + "secretsmanager:GetSecretValue" + - pattern: | + "rds:CopyDBSnapshot" + - pattern: | + "rds:CreateDBSnapshot" + - pattern: | + "ssm:*" + - pattern: | + "s3:*" + - pattern: | + "rds:*" + - pattern: | + "rn: secretsmanager:*" + message: >- + Ensure that IAM policies don't allow data exfiltration actions that are not resource-constrained. + This can allow the user to read sensitive data they don't need to read. + Instead, make sure that the user granted these privileges are given these permissions on specific + resources. + metadata: + references: + - https://github.com/bridgecrewio/checkov/blob/ca830e14745c2c8e1b941985f305abe985d7f1f9/checkov/terraform/checks/data/aws/IAMDataExfiltration.py + - https://cloudsplaining.readthedocs.io/en/latest/glossary/data-exfiltration/ + category: security + cwe: + - 'CWE-200: Exposure of Sensitive Information to an Unauthorized Actor' + license: Commons Clause License Condition v1.0[LGPL-2.1-only] + technology: + - terraform + - aws + owasp: + - A01:2021 - Broken Access Control + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.lang.security.iam.no-iam-priv-esc-funcs.no-iam-priv-esc-funcs + patterns: + - pattern-either: + - patterns: + - pattern-inside: | + resource $TYPE "..." { + ... + policy = jsonencode({ + ... + Statement = [ + ... + ] + ... + }) + ... + } + - pattern-not-inside: | + resource $TYPE "..." { + ... + policy = jsonencode({ + ... + Statement = [ + ..., + {... Effect = "Deny" ...}, + ... + ] + ... + }) + ... + } + - pattern: Action = $ACTION + - metavariable-pattern: + metavariable: $TYPE + pattern-either: + - pattern: | + "aws_iam_role_policy" + - pattern: | + "aws_iam_policy" + - pattern: | + "aws_iam_user_policy" + - pattern: | + "aws_iam_group_policy" + - patterns: + - pattern-inside: | + data aws_iam_policy_document "..." { + ... + statement { + ... + } + ... + } + - pattern-not-inside: | + data aws_iam_policy_document "..." { + ... + statement { + ... + effect = "Deny" + ... + } + ... + } + - pattern: | + actions = [..., $ACTION, ...] + - metavariable-pattern: + metavariable: $ACTION + pattern-either: + - pattern: | + "iam:AddUserToGroup" + - pattern: | + "iam:CreatePolicyVersion" + - pattern: | + "iam:SetDefaultPolicyVersion" + - pattern: | + "iam:AttachUserPolicy" + - pattern: | + "iam:AttachGroupPolicy" + - pattern: | + "iam:AttachRolePolicy" + - pattern: | + "iam:PutUserPolicy" + - pattern: | + "iam:PutGroupPolicy" + - pattern: | + "iam:PutRolePolicy" + - pattern: | + "glue:UpdateDevEndpoint" + - pattern: | + "iam:*" + - pattern: | + "glue:*" + message: >- + Ensure that actions that can result in privilege escalation are not used. + These actions could potentially result in an attacker gaining full administrator access of an AWS + account. + Try not to use these actions. + metadata: + references: + - https://rhinosecuritylabs.com/aws/aws-privilege-escalation-methods-mitigation/ + - https://cloudsplaining.readthedocs.io/en/latest/glossary/privilege-escalation/ + category: security + cwe: + - 'CWE-250: Execution with Unnecessary Privileges' + license: Commons Clause License Condition v1.0[LGPL-2.1-only] + technology: + - terraform + - aws + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.lang.security.iam.no-iam-priv-esc-other-users.no-iam-priv-esc-other-users + patterns: + - pattern-either: + - patterns: + - pattern-inside: | + resource $TYPE "..." { + ... + policy = jsonencode({ + ... + Statement = [ + ..., + {... Resource = $RESOURCE ...}, + ... + ] + ... + }) + ... + } + - pattern-not-inside: | + resource $TYPE "..." { + ... + policy = jsonencode({ + ... + Statement = [ + ..., + {... Effect = "Deny" ...}, + ... + ] + ... + }) + ... + } + - pattern: | + Action = $ACTION + - metavariable-pattern: + metavariable: $TYPE + pattern-either: + - pattern: | + "aws_iam_role_policy" + - pattern: | + "aws_iam_policy" + - pattern: | + "aws_iam_user_policy" + - pattern: | + "aws_iam_group_policy" + - patterns: + - pattern-inside: | + data aws_iam_policy_document "..." { + ... + statement { + ... + resources = $RESOURCE + ... + } + ... + } + - pattern-not-inside: | + data aws_iam_policy_document "..." { + ... + statement { + ... + effect = "Deny" + ... + } + ... + } + - pattern: | + actions = [..., $ACTION, ...] + - metavariable-pattern: + metavariable: $RESOURCE + pattern-either: + - pattern-regex: .*\*.* + - metavariable-pattern: + metavariable: $ACTION + pattern-either: + - pattern: | + "iam:CreateAccessKey" + - pattern: | + "iam:CreateLoginProfile" + - pattern: | + "iam:UpdateLoginProfile" + - pattern: | + "iam:*" + message: >- + Ensure that IAM policies with permissions on other users don't allow for privilege escalation. This + can lead to an attacker gaining full administrator access of AWS accounts. Instead, specify which + user the permission should be used on or do not use the listed actions. $RESOURCE + metadata: + references: + - https://cloudsplaining.readthedocs.io/en/latest/glossary/privilege-escalation/ + - https://github.com/bridgecrewio/checkov/blob/ca830e14745c2c8e1b941985f305abe985d7f1f9/checkov/terraform/checks/data/aws/IAMPrivilegeEscalation.py + category: security + cwe: + - 'CWE-269: Improper Privilege Management' + license: Commons Clause License Condition v1.0[LGPL-2.1-only] + technology: + - terraform + - aws + owasp: + - A04:2021 - Insecure Design + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.lang.security.iam.no-iam-priv-esc-roles.no-iam-priv-esc-roles + patterns: + - pattern-either: + - patterns: + - pattern-inside: | + resource $TYPE "..." { + ... + policy = jsonencode({ + ... + Statement = [ + ... + ] + ... + }) + ... + } + - pattern-not-inside: | + resource $TYPE "..." { + ... + policy = jsonencode({ + ... + Statement = [ + ..., + {... Effect = "Deny" ...}, + ... + ] + ... + }) + ... + } + - pattern: | + Action = $ACTION + - metavariable-pattern: + metavariable: $TYPE + pattern-either: + - pattern: | + "aws_iam_role_policy" + - pattern: | + "aws_iam_policy" + - pattern: | + "aws_iam_user_policy" + - pattern: | + "aws_iam_group_policy" + - patterns: + - pattern-inside: | + data aws_iam_policy_document "..." { + ... + statement { + ... + } + ... + } + - pattern-not-inside: | + data aws_iam_policy_document "..." { + ... + statement { + ... + effect = "Deny" + ... + } + ... + } + - pattern: | + actions = $ACTION + - metavariable-pattern: + metavariable: $ACTION + pattern-either: + # TODO: this is a hack because generic currently doesn't work with [..., $ACTION, ...] + # we will replace this once full support for terraform gets released. + - patterns: + - pattern: | + [..., "sts:AssumeRole", ...] + - pattern: | + [..., "iam:UpdateAssumeRolePolicy", ...] + - patterns: + - pattern: | + [..., "iam:PassRole", ...] + - pattern: | + [..., "lambda:CreateFunction", ...] + - pattern: | + [..., "lambda:InvokeFunction", ...] + - patterns: + - pattern: | + [..., "iam:PassRole", ...] + - pattern: | + [..., "lambda:CreateFunction", ...] + - pattern: | + [..., "lambda:CreateEventSourceMapping", ...] + - pattern: | + "lambda:UpdateFunctionCode" + - patterns: + - pattern: | + [..., "iam:PassRole", ...] + - pattern: | + [..., "glue:CreateDevEndpoint", ...] + - patterns: + - pattern: | + [..., "iam:PassRole", ...] + - pattern: | + [..., "cloudformation:CreateStack", ...] + - patterns: + - pattern: | + [..., "iam:PassRole", ...] + - pattern: | + [..., "datapipeline:CreatePipeline", ...] + - pattern: | + [..., "datapipeline:PutPipelineDefinition", ...] + message: >- + Ensure that groups of actions that include iam:PassRole and could result in privilege escalation + are not all allowed for the same user. These actions could result in an attacker gaining full admin + access of an AWS account. Try not to use these actions in conjuction. + metadata: + references: + - https://cloudsplaining.readthedocs.io/en/latest/glossary/privilege-escalation/ + - https://rhinosecuritylabs.com/aws/aws-privilege-escalation-methods-mitigation/ + category: security + cwe: + - 'CWE-269: Improper Privilege Management' + license: Commons Clause License Condition v1.0[LGPL-2.1-only] + technology: + - terraform + - aws + owasp: + - A04:2021 - Insecure Design + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.lang.security.iam.no-iam-resource-exposure.no-iam-resource-exposure + patterns: + - pattern-either: + - patterns: + - pattern-inside: | + resource $TYPE "..." { + ... + policy = jsonencode({ + ... + Statement = [ + ... + ] + ... + }) + ... + } + - pattern-not-inside: | + resource $TYPE "..." { + ... + policy = jsonencode({ + ... + Statement = [ + ..., + {... Effect = "Deny" ...}, + ... + ] + ... + }) + ... + } + - pattern: | + Action = $ACTION + - metavariable-pattern: + metavariable: $TYPE + pattern-either: + - pattern: | + "aws_iam_role_policy" + - pattern: | + "aws_iam_policy" + - pattern: | + "aws_iam_user_policy" + - pattern: | + "aws_iam_group_policy" + - patterns: + - pattern-inside: | + data aws_iam_policy_document "..." { + ... + statement { + ... + } + ... + } + - pattern-not-inside: | + data aws_iam_policy_document "..." { + ... + statement { + ... + effect = "Deny" + ... + } + ... + } + - pattern: | + actions = [..., $ACTION, ...] + - metavariable-pattern: + metavariable: $ACTION + pattern-either: + - pattern: | + "acm-pca:CreatePermission" + - pattern: | + "acm-pca:DeletePermission" + - pattern: | + "acm-pca:DeletePolicy" + - pattern: | + "acm-pca:PutPolicy" + - pattern: | + "apigateway:UpdateRestApiPolicy" + - pattern: | + "backup:DeleteBackupVaultAccessPolicy" + - pattern: | + "backup:PutBackupVaultAccessPolicy" + - pattern: | + "chime:DeleteVoiceConnectorTerminationCredentials" + - pattern: | + "chime:PutVoiceConnectorTerminationCredentials" + - pattern: | + "cloudformation:SetStackPolicy" + - pattern: | + "cloudsearch:UpdateServiceAccessPolicies" + - pattern: | + "codeartifact:DeleteDomainPermissionsPolicy" + - pattern: | + "codeartifact:DeleteRepositoryPermissionsPolicy" + - pattern: | + "codebuild:DeleteResourcePolicy" + - pattern: | + "codebuild:DeleteSourceCredentials" + - pattern: | + "codebuild:ImportSourceCredentials" + - pattern: | + "codebuild:PutResourcePolicy" + - pattern: | + "codeguru-profiler:PutPermission" + - pattern: | + "codeguru-profiler:RemovePermission" + - pattern: | + "codestar:AssociateTeamMember" + - pattern: | + "codestar:CreateProject" + - pattern: | + "codestar:DeleteProject" + - pattern: | + "codestar:DisassociateTeamMember" + - pattern: | + "codestar:UpdateTeamMember" + - pattern: | + "cognito-identity:CreateIdentityPool" + - pattern: | + "cognito-identity:DeleteIdentities" + - pattern: | + "cognito-identity:DeleteIdentityPool" + - pattern: | + "cognito-identity:GetId" + - pattern: | + "cognito-identity:MergeDeveloperIdentities" + - pattern: | + "cognito-identity:SetIdentityPoolRoles" + - pattern: | + "cognito-identity:UnlinkDeveloperIdentity" + - pattern: | + "cognito-identity:UnlinkIdentity" + - pattern: | + "cognito-identity:UpdateIdentityPool" + - pattern: | + "deeplens:AssociateServiceRoleToAccount" + - pattern: | + "ds:CreateConditionalForwarder" + - pattern: | + "ds:CreateDirectory" + - pattern: | + "ds:CreateMicrosoftAD" + - pattern: | + "ds:CreateTrust" + - pattern: | + "ds:ShareDirectory" + - pattern: | + "ec2:CreateNetworkInterfacePermission" + - pattern: | + "ec2:DeleteNetworkInterfacePermission" + - pattern: | + "ec2:ModifySnapshotAttribute" + - pattern: | + "ec2:ModifyVpcEndpointServicePermissions" + - pattern: | + "ec2:ResetSnapshotAttribute" + - pattern: | + "ecr:DeleteRepositoryPolicy" + - pattern: | + "ecr:SetRepositoryPolicy" + - pattern: | + "elasticfilesystem:DeleteFileSystemPolicy" + - pattern: | + "elasticfilesystem:PutFileSystemPolicy" + - pattern: | + "elasticmapreduce:PutBlockPublicAccessConfiguration" + - pattern: | + "es:CreateElasticsearchDomain" + - pattern: | + "es:UpdateElasticsearchDomainConfig" + - pattern: | + "glacier:AbortVaultLock" + - pattern: | + "glacier:CompleteVaultLock" + - pattern: | + "glacier:DeleteVaultAccessPolicy" + - pattern: | + "glacier:InitiateVaultLock" + - pattern: | + "glacier:SetDataRetrievalPolicy" + - pattern: | + "glacier:SetVaultAccessPolicy" + - pattern: | + "glue:DeleteResourcePolicy" + - pattern: | + "glue:PutResourcePolicy" + - pattern: | + "greengrass:AssociateServiceRoleToAccount" + - pattern: | + "health:DisableHealthServiceAccessForOrganization" + - pattern: | + "health:EnableHealthServiceAccessForOrganization" + - pattern: | + "iam:AddClientIDToOpenIDConnectProvider" + - pattern: | + "iam:AddRoleToInstanceProfile" + - pattern: | + "iam:AddUserToGroup" + - pattern: | + "iam:AttachGroupPolicy" + - pattern: | + "iam:AttachRolePolicy" + - pattern: | + "iam:AttachUserPolicy" + - pattern: | + "iam:ChangePassword" + - pattern: | + "iam:CreateAccessKey" + - pattern: | + "iam:CreateAccountAlias" + - pattern: | + "iam:CreateGroup" + - pattern: | + "iam:CreateInstanceProfile" + - pattern: | + "iam:CreateLoginProfile" + - pattern: | + "iam:CreateOpenIDConnectProvider" + - pattern: | + "iam:CreatePolicy" + - pattern: | + "iam:CreatePolicyVersion" + - pattern: | + "iam:CreateRole" + - pattern: | + "iam:CreateSAMLProvider" + - pattern: | + "iam:CreateServiceLinkedRole" + - pattern: | + "iam:CreateServiceSpecificCredential" + - pattern: | + "iam:CreateUser" + - pattern: | + "iam:CreateVirtualMFADevice" + - pattern: | + "iam:DeactivateMFADevice" + - pattern: | + "iam:DeleteAccessKey" + - pattern: | + "iam:DeleteAccountAlias" + - pattern: | + "iam:DeleteAccountPasswordPolicy" + - pattern: | + "iam:DeleteGroup" + - pattern: | + "iam:DeleteGroupPolicy" + - pattern: | + "iam:DeleteInstanceProfile" + - pattern: | + "iam:DeleteLoginProfile" + - pattern: | + "iam:DeleteOpenIDConnectProvider" + - pattern: | + "iam:DeletePolicy" + - pattern: | + "iam:DeletePolicyVersion" + - pattern: | + "iam:DeleteRole" + - pattern: | + "iam:DeleteRolePermissionsBoundary" + - pattern: | + "iam:DeleteRolePolicy" + - pattern: | + "iam:DeleteSAMLProvider" + - pattern: | + "iam:DeleteSSHPublicKey" + - pattern: | + "iam:DeleteServerCertificate" + - pattern: | + "iam:DeleteServiceLinkedRole" + - pattern: | + "iam:DeleteServiceSpecificCredential" + - pattern: | + "iam:DeleteSigningCertificate" + - pattern: | + "iam:DeleteUser" + - pattern: | + "iam:DeleteUserPermissionsBoundary" + - pattern: | + "iam:DeleteUserPolicy" + - pattern: | + "iam:DeleteVirtualMFADevice" + - pattern: | + "iam:DetachGroupPolicy" + - pattern: | + "iam:DetachRolePolicy" + - pattern: | + "iam:DetachUserPolicy" + - pattern: | + "iam:EnableMFADevice" + - pattern: | + "iam:PassRole" + - pattern: | + "iam:PutGroupPolicy" + - pattern: | + "iam:PutRolePermissionsBoundary" + - pattern: | + "iam:PutRolePolicy" + - pattern: | + "iam:PutUserPermissionsBoundary" + - pattern: | + "iam:PutUserPolicy" + - pattern: | + "iam:RemoveClientIDFromOpenIDConnectProvider" + - pattern: | + "iam:RemoveRoleFromInstanceProfile" + - pattern: | + "iam:RemoveUserFromGroup" + - pattern: | + "iam:ResetServiceSpecificCredential" + - pattern: | + "iam:ResyncMFADevice" + - pattern: | + "iam:SetDefaultPolicyVersion" + - pattern: | + "iam:SetSecurityTokenServicePreferences" + - pattern: | + "iam:UpdateAccessKey" + - pattern: | + "iam:UpdateAccountPasswordPolicy" + - pattern: | + "iam:UpdateAssumeRolePolicy" + - pattern: | + "iam:UpdateGroup" + - pattern: | + "iam:UpdateLoginProfile" + - pattern: | + "iam:UpdateOpenIDConnectProviderThumbprint" + - pattern: | + "iam:UpdateRole" + - pattern: | + "iam:UpdateRoleDescription" + - pattern: | + "iam:UpdateSAMLProvider" + - pattern: | + "iam:UpdateSSHPublicKey" + - pattern: | + "iam:UpdateServerCertificate" + - pattern: | + "iam:UpdateServiceSpecificCredential" + - pattern: | + "iam:UpdateSigningCertificate" + - pattern: | + "iam:UpdateUser" + - pattern: | + "iam:UploadSSHPublicKey" + - pattern: | + "iam:UploadServerCertificate" + - pattern: | + "iam:UploadSigningCertificate" + - pattern: | + "imagebuilder:PutComponentPolicy" + - pattern: | + "imagebuilder:PutImagePolicy" + - pattern: | + "imagebuilder:PutImageRecipePolicy" + - pattern: | + "iot:AttachPolicy" + - pattern: | + "iot:AttachPrincipalPolicy" + - pattern: | + "iot:DetachPolicy" + - pattern: | + "iot:DetachPrincipalPolicy" + - pattern: | + "iot:SetDefaultAuthorizer" + - pattern: | + "iot:SetDefaultPolicyVersion" + - pattern: | + "iotsitewise:CreateAccessPolicy" + - pattern: | + "iotsitewise:DeleteAccessPolicy" + - pattern: | + "iotsitewise:UpdateAccessPolicy" + - pattern: | + "kms:CreateGrant" + - pattern: | + "kms:PutKeyPolicy" + - pattern: | + "kms:RetireGrant" + - pattern: | + "kms:RevokeGrant" + - pattern: | + "lakeformation:BatchGrantPermissions" + - pattern: | + "lakeformation:BatchRevokePermissions" + - pattern: | + "lakeformation:GrantPermissions" + - pattern: | + "lakeformation:PutDataLakeSettings" + - pattern: | + "lakeformation:RevokePermissions" + - pattern: | + "lambda:AddLayerVersionPermission" + - pattern: | + "lambda:AddPermission" + - pattern: | + "lambda:DisableReplication" + - pattern: | + "lambda:EnableReplication" + - pattern: | + "lambda:RemoveLayerVersionPermission" + - pattern: | + "lambda:RemovePermission" + - pattern: | + "license-manager:UpdateServiceSettings" + - pattern: | + "lightsail:GetRelationalDatabaseMasterUserPassword" + - pattern: | + "logs:DeleteResourcePolicy" + - pattern: | + "logs:PutResourcePolicy" + - pattern: | + "mediapackage:RotateIngestEndpointCredentials" + - pattern: | + "mediastore:DeleteContainerPolicy" + - pattern: | + "mediastore:PutContainerPolicy" + - pattern: | + "opsworks:SetPermission" + - pattern: | + "opsworks:UpdateUserProfile" + - pattern: | + "quicksight:CreateAdmin" + - pattern: | + "quicksight:CreateGroup" + - pattern: | + "quicksight:CreateGroupMembership" + - pattern: | + "quicksight:CreateIAMPolicyAssignment" + - pattern: | + "quicksight:CreateUser" + - pattern: | + "quicksight:DeleteGroup" + - pattern: | + "quicksight:DeleteGroupMembership" + - pattern: | + "quicksight:DeleteIAMPolicyAssignment" + - pattern: | + "quicksight:DeleteUser" + - pattern: | + "quicksight:DeleteUserByPrincipalId" + - pattern: | + "quicksight:RegisterUser" + - pattern: | + "quicksight:UpdateDashboardPermissions" + - pattern: | + "quicksight:UpdateGroup" + - pattern: | + "quicksight:UpdateIAMPolicyAssignment" + - pattern: | + "quicksight:UpdateTemplatePermissions" + - pattern: | + "quicksight:UpdateUser" + - pattern: | + "ram:AcceptResourceShareInvitation" + - pattern: | + "ram:AssociateResourceShare" + - pattern: | + "ram:CreateResourceShare" + - pattern: | + "ram:DeleteResourceShare" + - pattern: | + "ram:DisassociateResourceShare" + - pattern: | + "ram:EnableSharingWithAwsOrganization" + - pattern: | + "ram:RejectResourceShareInvitation" + - pattern: | + "ram:UpdateResourceShare" + - pattern: | + "rds:AuthorizeDBSecurityGroupIngress" + - pattern: | + "rds-db:connect" + - pattern: | + "redshift:AuthorizeSnapshotAccess" + - pattern: | + "redshift:CreateClusterUser" + - pattern: | + "redshift:CreateSnapshotCopyGrant" + - pattern: | + "redshift:JoinGroup" + - pattern: | + "redshift:ModifyClusterIamRoles" + - pattern: | + "redshift:RevokeSnapshotAccess" + - pattern: | + "route53resolver:PutResolverRulePolicy" + - pattern: | + "s3:BypassGovernanceRetention" + - pattern: | + "s3:DeleteAccessPointPolicy" + - pattern: | + "s3:DeleteBucketPolicy" + - pattern: | + "s3:ObjectOwnerOverrideToBucketOwner" + - pattern: | + "s3:PutAccessPointPolicy" + - pattern: | + "s3:PutAccountPublicAccessBlock" + - pattern: | + "s3:PutBucketAcl" + - pattern: | + "s3:PutBucketPolicy" + - pattern: | + "s3:PutBucketPublicAccessBlock" + - pattern: | + "s3:PutObjectAcl" + - pattern: | + "s3:PutObjectVersionAcl" + - pattern: | + "secretsmanager:DeleteResourcePolicy" + - pattern: | + "secretsmanager:PutResourcePolicy" + - pattern: | + "secretsmanager:ValidateResourcePolicy" + - pattern: | + "servicecatalog:CreatePortfolioShare" + - pattern: | + "servicecatalog:DeletePortfolioShare" + - pattern: | + "sns:AddPermission" + - pattern: | + "sns:CreateTopic" + - pattern: | + "sns:RemovePermission" + - pattern: | + "sns:SetTopicAttributes" + - pattern: | + "sqs:AddPermission" + - pattern: | + "sqs:CreateQueue" + - pattern: | + "sqs:RemovePermission" + - pattern: | + "sqs:SetQueueAttributes" + - pattern: | + "ssm:ModifyDocumentPermission" + - pattern: | + "sso:AssociateDirectory" + - pattern: | + "sso:AssociateProfile" + - pattern: | + "sso:CreateApplicationInstance" + - pattern: | + "sso:CreateApplicationInstanceCertificate" + - pattern: | + "sso:CreatePermissionSet" + - pattern: | + "sso:CreateProfile" + - pattern: | + "sso:CreateTrust" + - pattern: | + "sso:DeleteApplicationInstance" + - pattern: | + "sso:DeleteApplicationInstanceCertificate" + - pattern: | + "sso:DeletePermissionSet" + - pattern: | + "sso:DeletePermissionsPolicy" + - pattern: | + "sso:DeleteProfile" + - pattern: | + "sso:DisassociateDirectory" + - pattern: | + "sso:DisassociateProfile" + - pattern: | + "sso:ImportApplicationInstanceServiceProviderMetadata" + - pattern: | + "sso:PutPermissionsPolicy" + - pattern: | + "sso:StartSSO" + - pattern: | + "sso:UpdateApplicationInstanceActiveCertificate" + - pattern: | + "sso:UpdateApplicationInstanceDisplayData" + - pattern: | + "sso:UpdateApplicationInstanceResponseConfiguration" + - pattern: | + "sso:UpdateApplicationInstanceResponseSchemaConfiguration" + - pattern: | + "sso:UpdateApplicationInstanceSecurityConfiguration" + - pattern: | + "sso:UpdateApplicationInstanceServiceProviderConfiguration" + - pattern: | + "sso:UpdateApplicationInstanceStatus" + - pattern: | + "sso:UpdateDirectoryAssociation" + - pattern: | + "sso:UpdatePermissionSet" + - pattern: | + "sso:UpdateProfile" + - pattern: | + "sso:UpdateSSOConfiguration" + - pattern: | + "sso:UpdateTrust" + - pattern: | + "sso-directory:AddMemberToGroup" + - pattern: | + "sso-directory:CreateAlias" + - pattern: | + "sso-directory:CreateGroup" + - pattern: | + "sso-directory:CreateUser" + - pattern: | + "sso-directory:DeleteGroup" + - pattern: | + "sso-directory:DeleteUser" + - pattern: | + "sso-directory:DisableUser" + - pattern: | + "sso-directory:EnableUser" + - pattern: | + "sso-directory:RemoveMemberFromGroup" + - pattern: | + "sso-directory:UpdateGroup" + - pattern: | + "sso-directory:UpdatePassword" + - pattern: | + "sso-directory:UpdateUser" + - pattern: | + "sso-directory:VerifyEmail" + - pattern: | + "storagegateway:DeleteChapCredentials" + - pattern: | + "storagegateway:SetLocalConsolePassword" + - pattern: | + "storagegateway:SetSMBGuestPassword" + - pattern: | + "storagegateway:UpdateChapCredentials" + - pattern: | + "waf:DeletePermissionPolicy" + - pattern: | + "waf:PutPermissionPolicy" + - pattern: | + "waf-regional:DeletePermissionPolicy" + - pattern: | + "waf-regional:PutPermissionPolicy" + - pattern: | + "wafv2:CreateWebACL" + - pattern: | + "wafv2:DeletePermissionPolicy" + - pattern: | + "wafv2:DeleteWebACL" + - pattern: | + "wafv2:PutPermissionPolicy" + - pattern: | + "wafv2:UpdateWebACL" + - pattern: | + "worklink:UpdateDevicePolicyConfiguration" + - pattern: | + "workmail:ResetPassword" + - pattern: | + "workmail:ResetUserPassword" + - pattern: | + "xray:PutEncryptionConfig" + - pattern: | + "worklink:*" + - pattern: | + "route53resolver:*" + - pattern: | + "es:*" + - pattern: | + "greengrass:*" + - pattern: | + "redshift:*" + - pattern: | + "license-manager:*" + - pattern: | + "rds:*" + - pattern: | + "lambda:*" + - pattern: | + "elasticfilesystem:*" + - pattern: | + "logs:*" + - pattern: | + "sso:*" + - pattern: | + "waf:*" + - pattern: | + "mediastore:*" + - pattern: | + "acm-pca:*" + - pattern: | + "sso-directory:*" + - pattern: | + "imagebuilder:*" + - pattern: | + "sqs:*" + - pattern: | + "codeguru-profiler:*" + - pattern: | + "wafv2:*" + - pattern: | + "cloudformation:*" + - pattern: | + "xray:*" + - pattern: | + "codeartifact:*" + - pattern: | + "iotsitewise:*" + - pattern: | + "workmail:*" + - pattern: | + "glue:*" + - pattern: | + "deeplens:*" + - pattern: | + "chime:*" + - pattern: | + "mediapackage:*" + - pattern: | + "opsworks:*" + - pattern: | + "ds:*" + - pattern: | + "ram:*" + - pattern: | + "iam:*" + - pattern: | + "waf-regional:*" + - pattern: | + "glacier:*" + - pattern: | + "cloudsearch:*" + - pattern: | + "lakeformation:*" + - pattern: | + "elasticmapreduce:*" + - pattern: | + "quicksight:*" + - pattern: | + "sns:*" + - pattern: | + "ec2:*" + - pattern: | + "health:*" + - pattern: | + "lightsail:*" + - pattern: | + "codestar:*" + - pattern: | + "kms:*" + - pattern: | + "codebuild:*" + - pattern: | + "s3:*" + - pattern: | + "cognito-identity:*" + - pattern: | + "apigateway:*" + - pattern: | + "rds-db:*" + - pattern: | + "iot:*" + - pattern: | + "backup:*" + - pattern: | + "secretsmanager:*" + - pattern: | + "servicecatalog:*" + - pattern: | + "ssm:*" + - pattern: | + "storagegateway:*" + - pattern: | + "ecr:*" + message: >- + Ensure IAM policies don't allow resource exposure. These actions can expose AWS resources to the public. + For example `ecr:SetRepositoryPolicy` could let an attacker retrieve container images. Instead, + use another action that doesn't expose AWS resources. + metadata: + references: + - https://cloudsplaining.readthedocs.io/en/latest/glossary/resource-exposure/ + - https://github.com/bridgecrewio/checkov/blob/ca830e14745c2c8e1b941985f305abe985d7f1f9/checkov/terraform/checks/data/aws/IAMPermissionsManagement.py + category: security + cwe: + - 'CWE-200: Exposure of Sensitive Information to an Unauthorized Actor' + license: Commons Clause License Condition v1.0[LGPL-2.1-only] + technology: + - terraform + - aws + owasp: + - A01:2021 - Broken Access Control + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.lang.security.iam.no-iam-star-actions.no-iam-star-actions + patterns: + - pattern-either: + - patterns: + - pattern-inside: | + resource $TYPE "..." { + ... + policy = jsonencode({ + ... + Statement = [ + ... + ] + ... + }) + ... + } + - pattern-not-inside: | + resource $TYPE "..." { + ... + policy = jsonencode({ + ... + Statement = [ + ..., + {... Effect = "Deny" ...}, + ... + ] + ... + }) + ... + } + - pattern-either: + - pattern: Action = "*" + - pattern: Action = ["*"] + - metavariable-pattern: + metavariable: $TYPE + pattern-either: + - pattern: | + "aws_iam_role_policy" + - pattern: | + "aws_iam_policy" + - pattern: | + "aws_iam_user_policy" + - pattern: | + "aws_iam_group_policy" + - patterns: + - pattern-inside: | + data aws_iam_policy_document "..." { + ... + statement { + ... + } + ... + } + - pattern-not-inside: | + data aws_iam_policy_document "..." { + ... + statement { + ... + effect = "Deny" + ... + } + ... + } + - pattern: | + actions = ["*"] + message: >- + Ensure that no IAM policies allow "*" as a statement's actions. This allows all actions + to be performed on the specified resources, and is a violation of the principle of least privilege. + Instead, specify the actions that a certain user or policy is allowed to take. + metadata: + references: + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy + - https://github.com/bridgecrewio/checkov/blob/ca830e14745c2c8e1b941985f305abe985d7f1f9/checkov/terraform/checks/data/aws/StarActionPolicyDocument.py + category: security + cwe: + - 'CWE-269: Improper Privilege Management' + license: Commons Clause License Condition v1.0[LGPL-2.1-only] + technology: + - terraform + - aws + owasp: + - A04:2021 - Insecure Design + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: [hcl] + severity: WARNING +- id: terraform.lang.security.rds-insecure-password-storage-in-source-code.rds-insecure-password-storage-in-source-code + pattern-either: + - patterns: + - pattern: password = "..." + - pattern-inside: | + resource "aws_db_instance" "..." { + ... + } + - patterns: + - pattern: master_password = "..." + - pattern-inside: | + resource "aws_rds_cluster" "..." { + ... + } + languages: + - hcl + severity: WARNING + message: >- + RDS instance or cluster with hardcoded credentials in source code. + It is recommended to pass the credentials at runtime, or generate random credentials using the random_password + resource. + metadata: + references: + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_instance#master_password + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/rds_cluster#master_password + - https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/password + cwe: + - 'CWE-522: Insufficiently Protected Credentials' + category: security + technology: + - terraform + - aws + owasp: + - A02:2017 - Broken Authentication + - A04:2021 - Insecure Design + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM +- id: terraform.lang.security.rds-public-access.rds-public-access + patterns: + - pattern: publicly_accessible = true + - pattern-inside: | + resource "aws_db_instance" "..." { + ... + } + languages: + - hcl + severity: WARNING + message: RDS instance accessible from the Internet detected. + metadata: + references: + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_instance#publicly_accessible + - https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_VPC.WorkingWithRDSInstanceinaVPC.html#USER_VPC.Hiding + cwe: + - 'CWE-284: Improper Access Control' + category: security + technology: + - terraform + - aws + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW +- id: terraform.lang.security.s3-cors-all-origins.all-origins-allowed + patterns: + - pattern-inside: cors_rule { ... } + - pattern: allowed_origins = ["*"] + languages: + - hcl + severity: WARNING + message: CORS rule on bucket permits any origin + metadata: + references: + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket#using-cors + cwe: + - 'CWE-942: Permissive Cross-domain Policy with Untrusted Domains' + category: security + technology: + - terraform + - aws + owasp: + - A05:2021 - Security Misconfiguration + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW +- id: terraform.lang.security.s3-public-read-bucket.s3-public-read-bucket + patterns: + - pattern-either: + - pattern: acl = "public-read" + - pattern: acl = "authenticated-read" + - pattern-not-inside: | + resource "aws_s3_bucket" "..." { + ... + website { ... } + ... + } + languages: + - hcl + severity: WARNING + message: S3 bucket with public read access detected. + metadata: + cwe: + - 'CWE-200: Exposure of Sensitive Information to an Unauthorized Actor' + references: + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket#acl + - https://docs.aws.amazon.com/AmazonS3/latest/dev/acl-overview.html#canned-acl + category: security + technology: + - terraform + - aws + owasp: + - A01:2021 - Broken Access Control + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW +- id: terraform.lang.security.s3-public-rw-bucket.s3-public-rw-bucket + pattern: acl = "public-read-write" + languages: + - hcl + severity: ERROR + message: S3 bucket with public read-write access detected. + metadata: + references: + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket#acl + - https://docs.aws.amazon.com/AmazonS3/latest/dev/acl-overview.html#canned-acl + cwe: + - 'CWE-200: Exposure of Sensitive Information to an Unauthorized Actor' + category: security + technology: + - terraform + - aws + owasp: + - A01:2021 - Broken Access Control + cwe2021-top25: true + subcategory: + - vuln + likelihood: LOW + impact: MEDIUM + confidence: MEDIUM +- id: terraform.lang.security.s3-unencrypted-bucket.s3-unencrypted-bucket + patterns: + - pattern: a + - pattern: b + languages: + - hcl + severity: INFO + message: >- + This rule has been deprecated, as all s3 buckets are encrypted by default with + no way to disable it. See https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_server_side_encryption_configuration + for more info. + metadata: + references: + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket#server_side_encryption_configuration + - https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucket-encryption.html + cwe: + - "CWE-311: Missing Encryption of Sensitive Data" + category: security + technology: + - terraform + - aws + owasp: + - A03:2017 - Sensitive Data Exposure + - A04:2021 - Insecure Design + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + deprecated: true +- id: typescript.angular.security.audit.angular-domsanitizer.angular-bypasssecuritytrust + message: >- + Detected the use of `$TRUST`. This can introduce a Cross-Site-Scripting + (XSS) vulnerability if this comes from user-provided input. If you have to + use `$TRUST`, ensure it does not come from user-input or use the + appropriate prevention mechanism e.g. input validation or + sanitization depending on the context. + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + references: + - https://angular.io/api/platform-browser/DomSanitizer + - https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + confidence: MEDIUM + category: security + technology: + - angular + - browser + license: Commons Clause License Condition v1.0[LGPL-2.1-only] + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: LOW + impact: MEDIUM + languages: + - typescript + severity: WARNING + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - pattern-inside: | + function ...({..., $X: string, ...}) { ... } + - pattern-inside: | + function ...(..., $X: string, ...) { ... } + - focus-metavariable: $X + pattern-sinks: + - patterns: + - pattern-either: + - pattern: $X.$TRUST($Y) + - focus-metavariable: $Y + - pattern-not: | + $X.$TRUST(`...`) + - pattern-not: | + $X.$TRUST("...") + - metavariable-regex: + metavariable: $TRUST + regex: (bypassSecurityTrustHtml|bypassSecurityTrustStyle|bypassSecurityTrustScript|bypassSecurityTrustUrl|bypassSecurityTrustResourceUrl) + pattern-sanitizers: + - patterns: + - pattern-either: + - pattern-inside: | + import $S from "underscore.string" + ... + - pattern-inside: | + import * as $S from "underscore.string" + ... + - pattern-inside: | + import $S from "underscore.string" + ... + - pattern-inside: | + $S = require("underscore.string") + ... + - pattern-either: + - pattern: $S.escapeHTML(...) + - patterns: + - pattern-either: + - pattern-inside: | + import $S from "dompurify" + ... + - pattern-inside: | + import { ..., $S,... } from "dompurify" + ... + - pattern-inside: | + import * as $S from "dompurify" + ... + - pattern-inside: | + $S = require("dompurify") + ... + - pattern-inside: | + import $S from "isomorphic-dompurify" + ... + - pattern-inside: | + import * as $S from "isomorphic-dompurify" + ... + - pattern-inside: | + $S = require("isomorphic-dompurify") + ... + - pattern-either: + - patterns: + - pattern-inside: | + $VALUE = $S(...) + ... + - pattern: $VALUE.sanitize(...) + - patterns: + - pattern-inside: | + $VALUE = $S.sanitize + ... + - pattern: $S(...) + - pattern: $S.sanitize(...) + - pattern: $S(...) + - patterns: + - pattern-either: + - pattern-inside: | + import $S from 'xss'; + ... + - pattern-inside: | + import * as $S from 'xss'; + ... + - pattern-inside: | + $S = require("xss") + ... + - pattern: $S(...) + - patterns: + - pattern-either: + - pattern-inside: | + import $S from 'sanitize-html'; + ... + - pattern-inside: | + import * as $S from "sanitize-html"; + ... + - pattern-inside: | + $S = require("sanitize-html") + ... + - pattern: $S(...) + - patterns: + - pattern: sanitizer.sanitize(...) + - pattern-not: sanitizer.sanitize(SecurityContext.NONE, ...); +- id: typescript.aws-cdk.security.audit.awscdk-bucket-encryption.awscdk-bucket-encryption + message: >- + Add "encryption: $Y.BucketEncryption.KMS_MANAGED" or "encryption: $Y.BucketEncryption.S3_MANAGED" + to the bucket props + for Bucket construct $X + metadata: + cwe: + - 'CWE-311: Missing Encryption of Sensitive Data' + category: security + technology: + - AWS-CDK + references: + - https://docs.aws.amazon.com/AmazonS3/latest/userguide/security-best-practices.html + owasp: + - A03:2017 - Sensitive Data Exposure + - A04:2021 - Insecure Design + subcategory: + - vuln + likelihood: LOW + impact: HIGH + confidence: MEDIUM + languages: + - typescript + severity: ERROR + pattern-either: + - patterns: + - pattern-inside: | + import {Bucket} from '@aws-cdk/aws-s3' + ... + - pattern: const $X = new Bucket(...) + - pattern-not: | + const $X = new Bucket(..., {..., encryption: BucketEncryption.KMS_MANAGED, ...}) + - pattern-not: | + const $X = new Bucket(..., {..., encryption: BucketEncryption.KMS, ...}) + - pattern-not: | + const $X = new Bucket(..., {..., encryption: BucketEncryption.S3_MANAGED, ...}) + - patterns: + - pattern-inside: | + import * as $Y from '@aws-cdk/aws-s3' + ... + - pattern: const $X = new $Y.Bucket(...) + - pattern-not: | + const $X = new $Y.Bucket(..., {..., encryption: $Y.BucketEncryption.KMS_MANAGED, ...}) + - pattern-not: | + const $X = new $Y.Bucket(..., {..., encryption: $Y.BucketEncryption.KMS, ...}) + - pattern-not: | + const $X = new $Y.Bucket(..., {..., encryption: $Y.BucketEncryption.S3_MANAGED, ...}) +- id: typescript.aws-cdk.security.audit.awscdk-bucket-enforcessl.aws-cdk-bucket-enforcessl + message: Bucket $X is not set to enforce encryption-in-transit, if not explictly setting this on the + bucket policy - the property "enforceSSL" should be set to true + metadata: + cwe: + - 'CWE-319: Cleartext Transmission of Sensitive Information' + category: security + technology: + - AWS-CDK + references: + - https://docs.aws.amazon.com/AmazonS3/latest/userguide/security-best-practices.html + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + languages: + - ts + severity: ERROR + pattern-either: + - patterns: + - pattern-inside: | + import {Bucket} from '@aws-cdk/aws-s3'; + ... + - pattern: const $X = new Bucket(...) + - pattern-not: | + const $X = new Bucket(..., {enforceSSL: true}, ...) + - patterns: + - pattern-inside: | + import * as $Y from '@aws-cdk/aws-s3'; + ... + - pattern: const $X = new $Y.Bucket(...) + - pattern-not: | + const $X = new $Y.Bucket(..., {..., enforceSSL: true, ...}) +- id: typescript.aws-cdk.security.audit.awscdk-sqs-unencryptedqueue.awscdk-sqs-unencryptedqueue + message: >- + Queue $X is missing encryption at rest. Add "encryption: $Y.QueueEncryption.KMS" or "encryption: $Y.QueueEncryption.KMS_MANAGED" + to the queue props to enable encryption at rest for the queue. + metadata: + category: security + cwe: + - 'CWE-311: Missing Encryption of Sensitive Data' + technology: + - AWS-CDK + references: + - https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-data-protection.html + owasp: + - A03:2017 - Sensitive Data Exposure + - A04:2021 - Insecure Design + subcategory: + - vuln + likelihood: LOW + impact: HIGH + confidence: MEDIUM + languages: + - ts + severity: WARNING + pattern-either: + - patterns: + - pattern-inside: | + import {Queue} from '@aws-cdk/aws-sqs' + ... + - pattern: const $X = new Queue(...) + - pattern-not: | + const $X = new Queue(..., {..., encryption: QueueEncryption.KMS_MANAGED, ...}) + - pattern-not: | + const $X = new Queue(..., {..., encryption: QueueEncryption.KMS, ...}) + - patterns: + - pattern-inside: | + import * as $Y from '@aws-cdk/aws-sqs' + ... + - pattern: const $X = new $Y.Queue(...) + - pattern-not: | + const $X = new $Y.Queue(..., {..., encryption: $Y.QueueEncryption.KMS_MANAGED, ...}) + - pattern-not: | + const $X = new $Y.Queue(..., {..., encryption: $Y.QueueEncryption.KMS, ...}) +- id: typescript.aws-cdk.security.awscdk-bucket-grantpublicaccessmethod.awscdk-bucket-grantpublicaccessmethod + message: Using the GrantPublicAccess method on bucket contruct $X will make the objects in the bucket + world accessible. Verify if this is intentional. + metadata: + cwe: + - 'CWE-306: Missing Authentication for Critical Function' + category: security + technology: + - AWS-CDK + references: + - https://docs.aws.amazon.com/AmazonS3/latest/userguide/access-control-overview.html + owasp: + - A07:2021 - Identification and Authentication Failures + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: HIGH + impact: HIGH + confidence: MEDIUM + languages: + - ts + severity: WARNING + pattern-either: + - patterns: + - pattern-inside: | + import {Bucket} from '@aws-cdk/aws-s3' + ... + - pattern: | + const $X = new Bucket(...) + ... + $X.grantPublicAccess(...) + - patterns: + - pattern-inside: | + import * as $Y from '@aws-cdk/aws-s3' + ... + - pattern: | + const $X = new $Y.Bucket(...) + ... + $X.grantPublicAccess(...) +- id: typescript.aws-cdk.security.awscdk-codebuild-project-public.awscdk-codebuild-project-public + message: CodeBuild Project $X is set to have a public URL. This will make the build results, logs, artifacts + publically accessible, including builds prior to the project being public. Ensure this is acceptable + for the project. + metadata: + category: security + cwe: + - 'CWE-306: Missing Authentication for Critical Function' + technology: + - AWS-CDK + references: + - https://docs.aws.amazon.com/codebuild/latest/userguide/public-builds.html + owasp: + - A07:2021 - Identification and Authentication Failures + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + languages: + - ts + severity: WARNING + pattern-either: + - patterns: + - pattern-inside: | + import {Project} from '@aws-cdk/aws-codebuild' + ... + - pattern: | + const $X = new Project(..., {..., badge: true, ...}) + - patterns: + - pattern-inside: | + import * as $Y from '@aws-cdk/aws-codebuild' + ... + - pattern: | + const $X = new $Y.Project(..., {..., badge: true, ...}) +- id: typescript.lang.best-practice.moment-deprecated.moment-deprecated + pattern: | + import 'moment' + message: Moment is a legacy project in maintenance mode. Consider using libraries that are actively supported, e.g. `dayjs`. + languages: + - typescript + - javascript + severity: INFO + metadata: + category: best-practice + technology: + - moment + - dayjs + references: + - 'https://momentjs.com/docs/#/-project-status/' + - 'https://day.js.org/' +- id: typescript.lang.correctness.useless-ternary.useless-ternary + pattern: | + $CONDITION ? $ANS : $ANS + message: + It looks like no matter how $CONDITION is evaluated, this expression returns $ANS. This is probably a copy-paste + error. + languages: + - typescript + - javascript + metadata: + category: correctness + technology: + - react + severity: ERROR +- id: typescript.lang.security.audit.cors-regex-wildcard.cors-regex-wildcard + message: "Unescaped '.' character in CORS domain regex $CORS: $PATTERN" + metadata: + cwe: + - 'CWE-183: Permissive List of Allowed Inputs' + category: security + technology: + - cors + owasp: + - A04:2021 - Insecure Design + references: + - https://owasp.org/Top10/A04_2021-Insecure_Design + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: + - ts + severity: WARNING + patterns: + - pattern-either: + - pattern: $CORS = [...,/$PATTERN/,...] + - pattern: $CORS = /$PATTERN/ + - focus-metavariable: $PATTERN + - metavariable-regex: + metavariable: $PATTERN + regex: .+?(?- + Access-Control-Allow-Origin response header is set to "*". This will disable CORS Same Origin Policy + restrictions. + metadata: + cwe: + - 'CWE-183: Permissive List of Allowed Inputs' + asvs: + section: 'V14: Configuration Verification Requirements' + control_id: 14.4.8 Permissive CORS + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x22-V14-Config.md#v144-http-security-headers-requirements + version: '4' + category: security + technology: + - nestjs + owasp: + - A04:2021 - Insecure Design + references: + - https://owasp.org/Top10/A04_2021-Insecure_Design + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: + - typescript + severity: WARNING + pattern-either: + - pattern: | + class $CN { + @Header("=~/[Aa][Cc][Cc][Ee][Ss][Ss]-[Cc][Oo][Nn][Tt][Rr][Oo][Ll]-[Aa][Ll][Ll][Oo][Ww]-[Oo][Rr][Ii][Gg][Ii][Nn]/", '*') + $FN(...) { + ... + } + } + - pattern: | + NestFactory.create($MODULE, {cors: true}) + - pattern: | + NestFactory.create($MODULE, {cors: {origin: '*'}}) + - pattern: | + $APP.enableCors() + - pattern: | + $APP.enableCors({origin: '*'}) +- id: typescript.nestjs.security.audit.nestjs-header-xss-disabled.nestjs-header-xss-disabled + message: >- + X-XSS-Protection header is set to 0. This will disable the browser's XSS Filter. + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + category: security + technology: + - nestjs + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + references: + - https://owasp.org/Top10/A03_2021-Injection + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: + - typescript + severity: WARNING + pattern: | + class $CN { + ... + @Header("=~/[Xx]-[Xx][Ss][Ss]-[Pp][Rr][Oo][Tt][Ee][Cc][Tt][Ii][Oo][Nn]/", '0') + $FN(...) { + ... + } + ... + } +- id: typescript.nestjs.security.audit.nestjs-open-redirect.nestjs-open-redirect + message: >- + Untrusted user input in {url: ...} can result in Open Redirect vulnerability. + metadata: + cwe: + - "CWE-601: URL Redirection to Untrusted Site ('Open Redirect')" + category: security + technology: + - nestjs + owasp: + - A01:2021 - Broken Access Control + references: + - https://owasp.org/Top10/A01_2021-Broken_Access_Control + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + languages: + - typescript + severity: WARNING + patterns: + - pattern: | + return {url: $URL} + - pattern-inside: | + class $CN { + @Redirect(...) + $FN(...) { + ... + } + } + - pattern-not: | + return {url: "..."} +- id: typescript.react.best-practice.define-styled-components-on-module-level.define-styled-components-on-module-level + patterns: + - pattern-inside: | + import styled from 'styled-components'; + ... + - pattern-either: + - pattern-inside: | + function $FUNC(...) { + ... + } + - pattern-inside: | + class $CLASS { + ... + } + - pattern-either: + - pattern: | + styled.$EL`...`; + - pattern: | + styled($EL)`...`; + message: >- + By declaring a styled component inside the render method of a react component, you are dynamically creating a new component on every render. This means that React will have to discard and re-calculate that part of the DOM subtree on each subsequent render, instead of just calculating the difference of what changed between them. This leads to performance bottlenecks and unpredictable behavior. + metadata: + references: + - https://styled-components.com/docs/faqs#why-should-i-avoid-declaring-styled-components-in-the-render-method + category: best-practice + technology: + - react + languages: + - typescript + - javascript + severity: WARNING +- id: typescript.react.best-practice.react-find-dom.react-find-dom + pattern-either: + - pattern: | + findDOMNode(...) + - pattern: | + $DOM.findDOMNode(...) + message: >- + findDOMNode is an escape hatch used to access the underlying DOM node. In most cases, use of this escape hatch is discouraged because it pierces the component abstraction. + metadata: + references: + - https://react.dev/reference/react-dom/findDOMNode + - https://github.com/yannickcr/eslint-plugin-react/issues/678#issue-165177220 + category: best-practice + technology: + - react + languages: + - typescript + - javascript + severity: WARNING +- id: typescript.react.best-practice.react-legacy-component.react-legacy-component + patterns: + - pattern: | + $METHOD(...) { + ... + } + - metavariable-regex: + metavariable: $METHOD + regex: componentWillMount|componentWillReceiveProps|componentWillUpdate + message: >- + Legacy component lifecycle was detected - $METHOD. + languages: + - typescript + - javascript + severity: WARNING + metadata: + category: best-practice + technology: + - react +- id: typescript.react.best-practice.react-props-in-state.react-props-in-state + pattern-either: + - patterns: + - pattern-inside: | + class $CN extends React.Component { + ... + } + - pattern-either: + - pattern: | + state = {$NAME: <... this.props.$PROP ...>} + - pattern: | + this.state = {$NAME: <... this.props.$PROP ...>} + - metavariable-regex: + metavariable: $NAME + regex: ^(?!default|initial).*$ + - patterns: + - pattern-either: + - pattern-inside: | + function $FN({$PROP},...) { + ... + } + - pattern-inside: | + function $FN($PROP,...) { + ... + } + - pattern-either: + - pattern: useState(<... $PROP ...>) + - pattern: useState(<... $PROP.$KEY ...>) + - pattern: | + useState(function $X(...) { + ... + <... $PROP ...> + ... + }) + - pattern: | + useState(function $X(...) { + ... + <... $PROP.$KEY ...> + ... + }) + - metavariable-regex: + metavariable: $PROP + regex: ^(?!default|initial).*$ + message: >- + Copying a prop into state in React -- this is bad practice as all updates + to it are ignored. Instead, read props directly in your component and avoid + copying props into state. + metadata: + references: + - https://overreacted.io/writing-resilient-components/#principle-1-dont-stop-the-data-flow + category: best-practice + technology: + - react + languages: + - typescript + - javascript + severity: WARNING +- id: typescript.react.best-practice.react-props-spreading.react-props-spreading + patterns: + - pattern: <$X {...$PROPS} /> + - focus-metavariable: $PROPS + message: >- + It's best practice to explicitly pass props to an HTML component rather than + use the spread operator. + The spread operator risks passing invalid HTML props to an HTML element, + which can cause console warnings or worse, give malicious actors a way + to inject unexpected attributes. + languages: + - typescript + - javascript + severity: WARNING + metadata: + source-rule-url: https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-props-no-spreading.md + references: + - https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-props-no-spreading.md + category: best-practice + technology: + - react + license: Commons Clause License Condition v1.0[LGPL-2.1-only] +- id: typescript.react.portability.i18next.i18next-key-format.i18next-key-format + patterns: + - pattern-either: + - patterns: + - pattern-either: + - pattern: t('$KEY') + - pattern: t('$KEY', $OPTIONS) + - pattern: t([$DYNAMIC_KEY, '$KEY']) + - pattern: t([$DYNAMIC_KEY, '$KEY'], $OPTIONS) + - metavariable-regex: + metavariable: $KEY + regex: (?!^[a-z0-9-]+\.[a-z0-9-]+\.[a-zA-Z0-9_.-]+$) + - patterns: + - pattern-either: + - pattern: t([$DYNAMIC_KEY, '$KEY']) + - pattern: t([$DYNAMIC_KEY, '$KEY'], $OPTIONS) + - metavariable-regex: + metavariable: $DYNAMIC_KEY + regex: (?!^[`][a-z0-9-]+[.][a-z0-9-]+[.]\S+$) + - patterns: + - pattern-either: + - pattern: $I18NEXT.t('$KEY') + - pattern: $I18NEXT.t('$KEY', $OPTIONS) + - pattern: $I18NEXT.t([$DYNAMIC_KEY, '$KEY']) + - pattern: $I18NEXT.t([$DYNAMIC_KEY, '$KEY'], $OPTIONS) + - metavariable-regex: + metavariable: $I18NEXT + regex: (^i18n|i18next$) + - metavariable-regex: + metavariable: $KEY + regex: (?!^[a-z0-9-]+\.[a-z0-9-]+\.[a-zA-Z0-9_.-]+$) + - patterns: + - pattern-either: + - pattern: $I18NEXT.t([$DYNAMIC_KEY, '$KEY']) + - pattern: $I18NEXT.t([$DYNAMIC_KEY, '$KEY'], $OPTIONS) + - metavariable-regex: + metavariable: $I18NEXT + regex: (^(i18n|i18next)$) + - metavariable-regex: + metavariable: $DYNAMIC_KEY + regex: (?!^[`][a-z0-9-]+[.][a-z0-9-]+[.]\S+$) + message: Translation key '$KEY' should match format 'MODULE.FEATURE.*' + languages: + - typescript + - javascript + severity: WARNING + metadata: + category: portability + technology: + - react + - mui + - i18next + references: + - https://www.notion.so/hendyirawan/Internationalization-Localization-Policy-318c21674e5f44c48d6f136a6eb2e024 + - https://mui.com/ + - https://react.i18next.com/ +- id: typescript.react.portability.i18next.jsx-label-not-i18n.jsx-label-not-i18n + patterns: + - pattern-either: + - pattern: + - pattern: + - metavariable-regex: + metavariable: $MESSAGE + regex: (.*[a-zA-Z]+.*) + - pattern-not: <$ELEMENT ... label="" ... /> + - pattern-not: <$ELEMENT ... label={t($KEY, ...)} ... /> + message: "JSX Component label not internationalized: '$MESSAGE'" + languages: + - typescript + - javascript + severity: WARNING + metadata: + category: portability + technology: + - react + - mui + - i18next + references: + - https://www.notion.so/hendyirawan/Internationalization-Localization-Policy-318c21674e5f44c48d6f136a6eb2e024 + - https://mui.com/ + - https://react.i18next.com/ +- id: typescript.react.portability.i18next.jsx-not-internationalized.jsx-not-internationalized + patterns: + - pattern: <$ELEMENT>$MESSAGE + - metavariable-regex: + metavariable: $MESSAGE + regex: ([A-Za-z\n ]+[A-Za-z]+[A-Za-z\n ]+) + - pattern-not: <$ELEMENT>t('$KEY', ...) + message: >- + JSX element not internationalized: '$MESSAGE'. + You should support different languages in your website or app with internationalization. + Instead, use packages such as `i18next` in order to internationalize your elements. + languages: + - typescript + - javascript + severity: WARNING + metadata: + category: portability + technology: + - react + - mui + - i18next + references: + - https://www.notion.so/hendyirawan/Internationalization-Localization-Policy-318c21674e5f44c48d6f136a6eb2e024 + - https://mui.com/ + - https://react.i18next.com/ +- id: typescript.react.portability.i18next.mui-snackbar-message.mui-snackbar-message + patterns: + - pattern: enqueueSnackbar('$MESSAGE', $X2) + - pattern-not: enqueueSnackbar(t($KEY), $X2) + message: 'React MUI enqueueSnackbar() title is not internationalized: ''$MESSAGE''' + languages: + - typescript + - javascript + severity: WARNING + metadata: + category: portability + technology: + - react + - mui + - i18next + references: + - https://hendyirawan.notion.site/Internationalization-Localization-Policy-318c21674e5f44c48d6f136a6eb2e024 + - https://mui.com/ + - https://react.i18next.com/ +- id: typescript.react.portability.i18next.useselect-label-not-i18n.useselect-label-not-i18n + patterns: + - pattern: useSelect($X1, $X2, '$LABEL', $X4) + - metavariable-regex: + metavariable: $LABEL + regex: (.*[A-Za-z].*) + - pattern-not: useSelect($X1, $X2, t('...'), $X4) + message: >- + React useSelect() label is not internationalized - '$LABEL'. + You should support different langauges in your website or app with internationalization. + Instead, use packages such as `i18next` to internationalize your elements. + languages: + - typescript + - javascript + severity: WARNING + metadata: + category: portability + technology: + - react + - mui + - i18next + references: + - https://www.notion.so/hendyirawan/Internationalization-Localization-Policy-318c21674e5f44c48d6f136a6eb2e024 + - https://react.i18next.com/ +- id: typescript.react.security.audit.react-dangerouslysetinnerhtml.react-dangerouslysetinnerhtml + message: >- + Detection of dangerouslySetInnerHTML from non-constant definition. This + can inadvertently expose users to cross-site scripting (XSS) attacks if + this comes from user-provided input. If you have to use + dangerouslySetInnerHTML, consider using a sanitization library such as + DOMPurify to sanitize your HTML. + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + references: + - https://react.dev/reference/react-dom/components/common#dangerously-setting-the-inner-html + category: security + confidence: MEDIUM + technology: + - react + license: Commons Clause License Condition v1.0[LGPL-2.1-only] + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + languages: + - typescript + - javascript + severity: WARNING + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - pattern-inside: | + function ...({..., $X, ...}) { ... } + - pattern-inside: | + function ...(..., $X, ...) { ... } + - focus-metavariable: $X + # Added to remove value.map which causes a fair amount of false positives + - pattern-not-inside: | + $F. ... .$SANITIZEUNC(...) + pattern-sinks: + - patterns: + - focus-metavariable: $X + - pattern-either: + - pattern: | + {...,dangerouslySetInnerHTML: {__html: $X},...} + - pattern: | + <$Y ... dangerouslySetInnerHTML={{__html: $X}} /> + - pattern-not: | + <$Y ... dangerouslySetInnerHTML={{__html: "..."}} /> + - pattern-not: | + {...,dangerouslySetInnerHTML:{__html: "..."},...} + - metavariable-pattern: + patterns: + - pattern-not: | + {...} + metavariable: $X + - pattern-not: | + <... {__html: "..."} ...> + - pattern-not: | + <... {__html: `...`} ...> + pattern-sanitizers: + - patterns: + - pattern-either: + - pattern-inside: | + import $S from "underscore.string" + ... + - pattern-inside: | + import * as $S from "underscore.string" + ... + - pattern-inside: | + import $S from "underscore.string" + ... + - pattern-inside: | + $S = require("underscore.string") + ... + - pattern-either: + - pattern: $S.escapeHTML(...) + - patterns: + - pattern-either: + - pattern-inside: | + import $S from "dompurify" + ... + - pattern-inside: | + import { ..., $S,... } from "dompurify" + ... + - pattern-inside: | + import * as $S from "dompurify" + ... + - pattern-inside: | + $S = require("dompurify") + ... + - pattern-inside: | + import $S from "isomorphic-dompurify" + ... + - pattern-inside: | + import * as $S from "isomorphic-dompurify" + ... + - pattern-inside: | + $S = require("isomorphic-dompurify") + ... + - pattern-either: + - patterns: + - pattern-inside: | + $VALUE = $S(...) + ... + - pattern: $VALUE.sanitize(...) + - patterns: + - pattern-inside: | + $VALUE = $S.sanitize + ... + - pattern: $S(...) + - pattern: $S.sanitize(...) + - pattern: $S(...) + - patterns: + - pattern-either: + - pattern-inside: | + import $S from 'xss'; + ... + - pattern-inside: | + import * as $S from 'xss'; + ... + - pattern-inside: | + $S = require("xss") + ... + - pattern: $S(...) + - patterns: + - pattern-either: + - pattern-inside: | + import $S from 'sanitize-html'; + ... + - pattern-inside: | + import * as $S from "sanitize-html"; + ... + - pattern-inside: | + $S = require("sanitize-html") + ... + - pattern: $S(...) + - patterns: + - pattern-either: + - pattern-inside: | + $S = new Remarkable() + ... + - pattern: $S.render(...) +- id: typescript.react.security.audit.react-href-var.react-href-var + message: >- + Detected a variable used in an anchor tag with the 'href' attribute. A + malicious actor may be able to input the 'javascript:' URI, which could + cause cross-site scripting (XSS). It is recommended to disallow + 'javascript:' URIs within your application. + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation + ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + references: + - https://reactjs.org/blog/2019/08/08/react-v16.9.0.html#deprecating-javascript-urls + - https://pragmaticwebsecurity.com/articles/spasecurity/react-xss-part1.html + category: security + confidence: LOW + technology: + - react + license: Commons Clause License Condition v1.0[LGPL-2.1-only] + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + languages: + - typescript + - javascript + severity: WARNING + mode: taint + pattern-sources: + - label: TAINTED + patterns: + - pattern-either: + - pattern-inside: | + function ...({..., $X, ...}) { ... } + - pattern-inside: | + function ...(..., $X, ...) { ... } + - focus-metavariable: $X + # This rule causes too many false positives without this addition + - pattern-either: + - pattern: $X.$Y + - pattern: $X[...] + # this removes .map(...) etc which likely comes from hard coded values. + - pattern-not-inside: | + $F. ... .$SANITIZEUNC(...) + - label: CONCAT + requires: TAINTED + patterns: + - pattern-either: + - pattern: | + `...${$X}...` + - pattern: | + $SANITIZE + <... $X ...> + - pattern-not: | + `${$X}...` + - pattern-not: | + $X + ... + - focus-metavariable: $X + - label: CLEAN + by-side-effect: true + patterns: + - pattern-either: + - pattern: $A($SOURCE) + - pattern: $SANITIZE. ... .$A($SOURCE) + - pattern: $A. ... .$SANITIZE($SOURCE) + - focus-metavariable: $SOURCE + - metavariable-regex: + metavariable: $A + regex: (?i)(.*valid|.*sanitiz) + pattern-sinks: + - requires: TAINTED and not CONCAT and not CLEAN + patterns: + - focus-metavariable: $X + - pattern-either: + - pattern: | + <$EL href={$X} /> + - pattern: | + React.createElement($EL, {href: $X}) + - pattern-inside: | + $PARAMS = {href: $X}; + ... + React.createElement($EL, $PARAMS); + - metavariable-pattern: + patterns: + - pattern-not-regex: (?i)(button) + metavariable: $EL +- id: typescript.react.security.audit.react-jwt-decoded-property.react-jwt-decoded-property + message: >- + Property decoded from JWT token without verifying and cannot be trustworthy. + metadata: + cwe: + - 'CWE-922: Insecure Storage of Sensitive Information' + references: + - https://pragmaticwebsecurity.com/articles/oauthoidc/localstorage-xss.html + category: security + owasp: + - A01:2021 - Broken Access Control + technology: + - react + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: + - typescript + - javascript + severity: INFO + patterns: + - pattern-inside: | + import jwt_decode from "jwt-decode"; + ... + - pattern-inside: | + $DECODED = jwt_decode($TOKEN,...); + ... + - pattern: $DECODED.$PROPERTY +- id: typescript.react.security.audit.react-jwt-in-localstorage.react-jwt-in-localstorage + message: >- + Storing JWT tokens in localStorage known to be a bad practice, consider moving your tokens from localStorage + to a HTTP cookie. + metadata: + cwe: + - 'CWE-922: Insecure Storage of Sensitive Information' + references: + - https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies + category: security + owasp: + - A01:2021 - Broken Access Control + technology: + - react + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: + - typescript + - javascript + severity: INFO + patterns: + - pattern-inside: | + import jwt_decode from "jwt-decode"; + ... + - pattern-either: + - pattern: | + $DECODED = jwt_decode($TOKEN,...); + ... + localStorage.setItem($NAME, <... $TOKEN ...>); + - pattern: | + $DECODED = jwt_decode(...); + ... + localStorage.setItem($NAME, <... $DECODED ...>); +- id: typescript.react.security.audit.react-unsanitized-method.react-unsanitized-method + message: >- + Detection of $HTML from non-constant definition. This + can inadvertently expose users to cross-site scripting (XSS) attacks if this + comes from user-provided input. If you have to use $HTML, + consider using a sanitization library such as DOMPurify to sanitize your HTML. + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + references: + - https://developer.mozilla.org/en-US/docs/Web/API/Document/writeln + - https://developer.mozilla.org/en-US/docs/Web/API/Document/write + - https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentHTML + category: security + confidence: MEDIUM + technology: + - react + license: Commons Clause License Condition v1.0[LGPL-2.1-only] + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: HIGH + impact: MEDIUM + languages: + - typescript + - javascript + severity: WARNING + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - pattern-inside: | + function ...({..., $X, ...}) { ... } + - pattern-inside: | + function ...(..., $X, ...) { ... } + - focus-metavariable: $X + - pattern-either: + - pattern: $X.$Y + - pattern: $X[...] + pattern-sinks: + - patterns: + - pattern-either: + - pattern: | + this.window.document. ... .$HTML('...',$SINK) + - pattern: | + window.document. ... .$HTML('...',$SINK) + - pattern: | + document.$HTML($SINK) + - metavariable-regex: + metavariable: $HTML + regex: (writeln|write) + - focus-metavariable: $SINK + - patterns: + - pattern-either: + - pattern: | + $PROP. ... .$HTML('...',$SINK) + - metavariable-regex: + metavariable: $HTML + regex: (insertAdjacentHTML) + - focus-metavariable: $SINK + pattern-sanitizers: + - patterns: + - pattern-either: + - pattern-inside: | + import $S from "underscore.string" + ... + - pattern-inside: | + import * as $S from "underscore.string" + ... + - pattern-inside: | + import $S from "underscore.string" + ... + - pattern-inside: | + $S = require("underscore.string") + ... + - pattern-either: + - pattern: $S.escapeHTML(...) + - patterns: + - pattern-either: + - pattern-inside: | + import $S from "dompurify" + ... + - pattern-inside: | + import { ..., $S,... } from "dompurify" + ... + - pattern-inside: | + import * as $S from "dompurify" + ... + - pattern-inside: | + $S = require("dompurify") + ... + - pattern-inside: | + import $S from "isomorphic-dompurify" + ... + - pattern-inside: | + import * as $S from "isomorphic-dompurify" + ... + - pattern-inside: | + $S = require("isomorphic-dompurify") + ... + - pattern-either: + - patterns: + - pattern-inside: | + $VALUE = $S(...) + ... + - pattern: $VALUE.sanitize(...) + - patterns: + - pattern-inside: | + $VALUE = $S.sanitize + ... + - pattern: $S(...) + - pattern: $S.sanitize(...) + - pattern: $S(...) + - patterns: + - pattern-either: + - pattern-inside: | + import $S from 'xss'; + ... + - pattern-inside: | + import * as $S from 'xss'; + ... + - pattern-inside: | + $S = require("xss") + ... + - pattern: $S(...) + - patterns: + - pattern-either: + - pattern-inside: | + import $S from 'sanitize-html'; + ... + - pattern-inside: | + import * as $S from "sanitize-html"; + ... + - pattern-inside: | + $S = require("sanitize-html") + ... + - pattern: $S(...) + - patterns: + - pattern-either: + - pattern-inside: | + $S = new Remarkable() + ... + - pattern: $S.render(...) +- id: typescript.react.security.audit.react-unsanitized-property.react-unsanitized-property + message: >- + Detection of $HTML from non-constant definition. This + can inadvertently expose users to cross-site scripting (XSS) attacks if this + comes from user-provided input. If you have to use $HTML, consider using + a sanitization library such as DOMPurify to sanitize your HTML. + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + references: + - https://react.dev/reference/react-dom/components/common#dangerously-setting-the-inner-html + category: security + confidence: MEDIUM + technology: + - react + license: Commons Clause License Condition v1.0[LGPL-2.1-only] + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + languages: + - typescript + - javascript + severity: WARNING + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - pattern-inside: | + function ...({..., $X, ...}) { ... } + - pattern-inside: | + function ...(..., $X, ...) { ... } + - focus-metavariable: $X + - pattern-either: + - pattern: $X.$Y + - pattern: $X[...] + pattern-sinks: + - patterns: + - pattern-either: + - pattern-inside: | + $BODY = $REACT.useRef(...) + ... + - pattern-inside: | + $BODY = useRef(...) + ... + - pattern-inside: | + $BODY = findDOMNode(...) + ... + - pattern-inside: | + $BODY = createRef(...) + ... + - pattern-inside: | + $BODY = $REACT.findDOMNode(...) + ... + - pattern-inside: | + $BODY = $REACT.createRef(...) + ... + - pattern-either: + - pattern: | + $BODY. ... .$HTML = $SINK + - pattern: | + $BODY.$HTML = $SINK + - metavariable-regex: + metavariable: $HTML + regex: (innerHTML|outerHTML) + - focus-metavariable: $SINK + - patterns: + - pattern-either: + - pattern: ReactDOM.findDOMNode(...).$HTML = $SINK + - metavariable-regex: + metavariable: $HTML + regex: (innerHTML|outerHTML) + - focus-metavariable: $SINK + pattern-sanitizers: + - patterns: + - pattern-either: + - pattern-inside: | + import $S from "underscore.string" + ... + - pattern-inside: | + import * as $S from "underscore.string" + ... + - pattern-inside: | + import $S from "underscore.string" + ... + - pattern-inside: | + $S = require("underscore.string") + ... + - pattern-either: + - pattern: $S.escapeHTML(...) + - patterns: + - pattern-either: + - pattern-inside: | + import $S from "dompurify" + ... + - pattern-inside: | + import { ..., $S,... } from "dompurify" + ... + - pattern-inside: | + import * as $S from "dompurify" + ... + - pattern-inside: | + $S = require("dompurify") + ... + - pattern-inside: | + import $S from "isomorphic-dompurify" + ... + - pattern-inside: | + import * as $S from "isomorphic-dompurify" + ... + - pattern-inside: | + $S = require("isomorphic-dompurify") + ... + - pattern-either: + - patterns: + - pattern-inside: | + $VALUE = $S(...) + ... + - pattern: $VALUE.sanitize(...) + - patterns: + - pattern-inside: | + $VALUE = $S.sanitize + ... + - pattern: $S(...) + - pattern: $S.sanitize(...) + - pattern: $S(...) + - patterns: + - pattern-either: + - pattern-inside: | + import $S from 'xss'; + ... + - pattern-inside: | + import * as $S from 'xss'; + ... + - pattern-inside: | + $S = require("xss") + ... + - pattern: $S(...) + - patterns: + - pattern-either: + - pattern-inside: | + import $S from 'sanitize-html'; + ... + - pattern-inside: | + import * as $S from "sanitize-html"; + ... + - pattern-inside: | + $S = require("sanitize-html") + ... + - pattern: $S(...) + - patterns: + - pattern-either: + - pattern-inside: | + $S = new Remarkable() + ... + - pattern: $S.render(...) +- id: typescript.react.security.react-insecure-request.react-insecure-request + message: >- + Unencrypted request over HTTP detected. + metadata: + vulnerability: Insecure Transport + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + cwe: + - 'CWE-319: Cleartext Transmission of Sensitive Information' + references: + - https://www.npmjs.com/package/axios + category: security + technology: + - react + subcategory: + - vuln + likelihood: LOW + impact: MEDIUM + confidence: MEDIUM + languages: + - typescript + - javascript + severity: ERROR + pattern-either: + - patterns: + - pattern-either: + - pattern-inside: | + import $AXIOS from 'axios'; + ... + $AXIOS.$METHOD(...) + - pattern-inside: | + $AXIOS = require('axios'); + ... + $AXIOS.$METHOD(...) + - pattern-either: + - pattern: $AXIOS.get("=~/[Hh][Tt][Tt][Pp]:\/\/.*/",...) + - pattern: $AXIOS.post("=~/[Hh][Tt][Tt][Pp]:\/\/.*/",...) + - pattern: $AXIOS.delete("=~/[Hh][Tt][Tt][Pp]:\/\/.*/",...) + - pattern: $AXIOS.head("=~/[Hh][Tt][Tt][Pp]:\/\/.*/",...) + - pattern: $AXIOS.patch("=~/[Hh][Tt][Tt][Pp]:\/\/.*/",...) + - pattern: $AXIOS.put("=~/[Hh][Tt][Tt][Pp]:\/\/.*/",...) + - pattern: $AXIOS.options("=~/[Hh][Tt][Tt][Pp]:\/\/.*/",...) + - patterns: + - pattern-either: + - pattern-inside: | + import $AXIOS from 'axios'; + ... + $AXIOS(...) + - pattern-inside: | + $AXIOS = require('axios'); + ... + $AXIOS(...) + - pattern-either: + - pattern: '$AXIOS({url: "=~/[Hh][Tt][Tt][Pp]:\/\/.*/"}, ...)' + - pattern: | + $OPTS = {url: "=~/[Hh][Tt][Tt][Pp]:\/\/.*/"} + ... + $AXIOS($OPTS, ...) + - pattern: fetch("=~/[Hh][Tt][Tt][Pp]:\/\/.*/", ...) +- id: typescript.react.security.react-markdown-insecure-html.react-markdown-insecure-html + message: >- + Overwriting `transformLinkUri` or `transformImageUri` to something insecure, or turning `allowDangerousHtml` + on, or turning `escapeHtml` off, will open the code up to XSS vectors. + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + references: + - https://www.npmjs.com/package/react-markdown#security + category: security + technology: + - react + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: + - typescript + - javascript + severity: WARNING + patterns: + - pattern-either: + - pattern-inside: | + $X = require('react-markdown/with-html'); + ... + - pattern-inside: | + $X = require('react-markdown'); + ... + - pattern-inside: | + import 'react-markdown/with-html'; + ... + - pattern-inside: | + import 'react-markdown'; + ... + - pattern-either: + - pattern: | + <$EL allowDangerousHtml /> + - pattern: | + <$EL escapeHtml={false} /> + - pattern: | + <$EL transformLinkUri=... /> + - pattern: | + <$EL transformImageUri=... /> +- id: yaml.argo.correctness.event-binding-payload-with-hyphen.event-binding-payload-with-hyphen + languages: [yaml] + severity: WARNING + message: The parameter `$VALUE` to this WorkflowEventBinding includes hyphens, which will, very confusingly, throw an error when Argo Workflows tries to invoke the workflow. Set the payload value to use underscores instead. + metadata: + category: correctness + references: + - https://argoproj.github.io/argo-workflows/variables/#expression + technology: + - argo + - argo-workflows + match: + all: + - inside: | + apiVersion: argoproj.io/v1alpha1 + kind: WorkflowEventBinding + ... + - inside: | + spec: + ... + submit: + ... + arguments: + ... + parameters: + ... + - | + event: $VALUE + where: + - metavariable: $VALUE + regex: >- + payload\..*-.* +- id: yaml.argo.security.argo-workflow-parameter-command-injection.argo-workflow-parameter-command-injection + message: Using input or workflow parameters in here-scripts can lead to command injection or code injection. Convert the parameters to env variables instead. + languages: [yaml] + metadata: + category: security + cwe: + - "CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')" + - "CWE-94: Improper Control of Generation of Code ('Code Injection')" + owasp: + - A03:2021 – Injection + confidence: MEDIUM + likelihood: MEDIUM + impact: HIGH + subcategory: + - vuln + references: + - https://github.com/argoproj/argo-workflows/issues/5061 + - https://github.com/argoproj/argo-workflows/issues/5114#issue-808865370 + technology: + - ci + - argo + severity: ERROR + patterns: + - pattern-inside: | + apiVersion: $VERSION + ... + - metavariable-regex: + metavariable: $VERSION + regex: (argoproj.io.*) + - pattern-either: + - patterns: + - pattern-inside: | + command: + ... + - python + ... + ... + source: + $SCRIPT + - focus-metavariable: $SCRIPT + - metavariable-pattern: + metavariable: $SCRIPT + language: python + patterns: + - pattern: | + $FUNC(..., $PARAM, ...) + - metavariable-pattern: + metavariable: $PARAM + pattern-either: + - pattern-regex: (.*{{.*inputs.parameters.*}}.*) + - pattern-regex: (.*{{.*workflow.parameters.*}}.*) + - patterns: + - pattern-inside: | + command: + ... + - $LANG + ... + ... + source: + $SCRIPT + - metavariable-regex: + metavariable: $LANG + regex: (bash|sh) + - focus-metavariable: $SCRIPT + - metavariable-pattern: + metavariable: $SCRIPT + language: bash + patterns: + - pattern: | + $CMD ... $PARAM ... + - metavariable-pattern: + metavariable: $PARAM + pattern-either: + - pattern-regex: (.*{{.*inputs.parameters.*}}.*) + - pattern-regex: (.*{{.*workflow.parameters.*}}.*) + - patterns: + - pattern-inside: | + container: + ... + command: $LANG + ... + args: $PARAM + - metavariable-regex: + metavariable: $LANG + regex: .*(sh|bash|ksh|csh|tcsh|zsh).* + - metavariable-pattern: + metavariable: $PARAM + pattern-either: + - pattern-regex: (.*{{.*inputs.parameters.*}}.*) + - pattern-regex: (.*{{.*workflow.parameters.*}}.*) + - focus-metavariable: $PARAM +- id: yaml.docker-compose.security.exposing-docker-socket-volume.exposing-docker-socket-volume + patterns: + - pattern-inside: | + version: ... + ... + - pattern-either: + - pattern: | + volumes: + - ... + - /var/run/docker.sock:/var/run/docker.sock + - ... + - pattern: | + volumes: + - ... + - /run/docker.sock:/run/docker.sock + - ... + - pattern: | + volumes: + - ... + - /var/run/docker.sock:/run/docker.sock + - ... + - pattern: | + volumes: + - ... + - /run/docker.sock:/var/run/docker.sock + - ... + - pattern: | + volumes: + - ... + - /var/run/docker.sock + - ... + - pattern: | + volumes: + - ... + - /run/docker.sock + - ... + - pattern: | + volumes: + - ... + - ... + source: /var/run/docker.sock + ... + - ... + - pattern: | + volumes: + - ... + - ... + source: /run/docker.sock + ... + - ... + message: >- + Exposing host's Docker socket to containers via a volume. The owner of this + socket is root. Giving someone access to it is equivalent to giving + unrestricted root access to your host. Remove 'docker.sock' from volumes to + prevent this. + metadata: + references: + - https://docs.docker.com/compose/compose-file/compose-file-v3/#volume-configuration-reference + - https://cheatsheetseries.owasp.org/cheatsheets/Docker_Security_Cheat_Sheet.html#rule-1-do-not-expose-the-docker-daemon-socket-even-to-the-containers + category: security + technology: + - docker-compose + cwe: + - 'CWE-250: Execution with Unnecessary Privileges' + owasp: + - A06:2017 - Security Misconfiguration + - A05:2021 - Security Misconfiguration + subcategory: + - audit + likelihood: LOW + impact: HIGH + confidence: LOW + languages: [yaml] + severity: WARNING +- id: yaml.docker-compose.security.no-new-privileges.no-new-privileges + patterns: + - pattern-inside: | + version: ... + ... + services: + ... + - pattern: | + $SERVICE: + ... + image: ... + - pattern-not: | + $SERVICE: + ... + image: ... + ... + security_opt: + - ... + - no-new-privileges:true + - ... + - focus-metavariable: $SERVICE + message: >- + Service '$SERVICE' allows for privilege escalation via setuid or setgid + binaries. Add 'no-new-privileges:true' in 'security_opt' to prevent this. + metadata: + cwe: + - 'CWE-732: Incorrect Permission Assignment for Critical Resource' + owasp: + - A05:2021 - Security Misconfiguration + - A06:2017 - Security Misconfiguration + references: + - https://raesene.github.io/blog/2019/06/01/docker-capabilities-and-no-new-privs/ + - https://www.kernel.org/doc/Documentation/prctl/no_new_privs.txt + - https://cheatsheetseries.owasp.org/cheatsheets/Docker_Security_Cheat_Sheet.html#rule-4-add-no-new-privileges-flag + category: security + technology: + - docker-compose + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH + confidence: LOW + languages: [yaml] + severity: WARNING +- id: yaml.docker-compose.security.privileged-service.privileged-service + patterns: + - pattern-inside: | + version: ... + ... + services: + ... + $SERVICE: + ... + privileged: $TRUE + - focus-metavariable: $TRUE + - metavariable-regex: + metavariable: $TRUE + regex: (true) + fix: | + false + message: >- + Service '$SERVICE' is running in privileged mode. This grants the + container the equivalent of root capabilities on the host machine. This + can lead to container escapes, privilege escalation, and other security + concerns. Remove the 'privileged' key to disable this capability. + metadata: + cwe: + - 'CWE-250: Execution with Unnecessary Privileges' + owasp: + - A06:2017 - Security Misconfiguration + - A05:2021 - Security Misconfiguration + references: + - https://www.trendmicro.com/en_us/research/19/l/why-running-a-privileged-container-in-docker-is-a-bad-idea.html + - https://containerjournal.com/topics/container-security/why-running-a-privileged-container-is-not-a-good-idea/ + category: security + technology: + - docker-compose + license: Commons Clause License Condition v1.0[LGPL-2.1-only] + subcategory: + - vuln + likelihood: HIGH + impact: HIGH + confidence: HIGH + languages: + - yaml + severity: WARNING +- id: yaml.docker-compose.security.seccomp-confinement-disabled.seccomp-confinement-disabled + patterns: + - pattern-inside: | + version: ... + ... + services: + ... + - pattern: | + $SERVICE: + ... + image: ... + ... + security_opt: + - ... + - seccomp:unconfined + message: >- + Service '$SERVICE' is explicitly disabling seccomp confinement. This runs + the service in an unrestricted state. Remove 'seccomp:unconfined' to prevent this. + metadata: + cwe: + - 'CWE-284: Improper Access Control' + references: + - https://docs.docker.com/engine/security/seccomp/ + category: security + technology: + - docker-compose + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + subcategory: + - audit + likelihood: LOW + impact: HIGH + confidence: LOW + languages: [yaml] + severity: WARNING +- id: yaml.docker-compose.security.selinux-separation-disabled.selinux-separation-disabled + patterns: + - pattern-inside: | + version: ... + ... + services: + ... + - pattern: | + $SERVICE: + ... + image: ... + ... + security_opt: + - ... + - label:disable + message: >- + Service '$SERVICE' is explicitly disabling SELinux separation. This runs the + service as an unconfined type. Remove 'label:disable' to prevent this. + metadata: + cwe: + - 'CWE-284: Improper Access Control' + references: + - https://www.projectatomic.io/blog/2016/03/dwalsh_selinux_containers/ + - https://docs.docker.com/engine/reference/run/#security-configuration + category: security + technology: + - docker-compose + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + subcategory: + - audit + likelihood: LOW + impact: HIGH + confidence: LOW + languages: [yaml] + severity: WARNING +- id: yaml.docker-compose.security.writable-filesystem-service.writable-filesystem-service + patterns: + - pattern-inside: | + version: ... + ... + services: + ... + - pattern: | + $SERVICE: + ... + image: ... + ... + - pattern-not: | + $SERVICE: + ... + image: ... + ... + read_only: true + - focus-metavariable: $SERVICE + message: >- + Service '$SERVICE' is running with a writable root filesystem. This may + allow malicious applications to download and run additional payloads, or + modify container files. If an application inside a container has to save + something temporarily consider using a tmpfs. Add 'read_only: true' to this + service to prevent this. + metadata: + cwe: + - 'CWE-732: Incorrect Permission Assignment for Critical Resource' + owasp: + - A05:2021 - Security Misconfiguration + - A06:2017 - Security Misconfiguration + references: + - https://docs.docker.com/compose/compose-file/compose-file-v3/#domainname-hostname-ipc-mac_address-privileged-read_only-shm_size-stdin_open-tty-user-working_dir + - https://blog.atomist.com/security-of-docker-kubernetes/ + - https://cheatsheetseries.owasp.org/cheatsheets/Docker_Security_Cheat_Sheet.html#rule-8-set-filesystem-and-volumes-to-read-only + category: security + technology: + - docker-compose + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH + confidence: LOW + languages: [yaml] + severity: WARNING +- id: yaml.github-actions.security.allowed-unsecure-commands.allowed-unsecure-commands + languages: [yaml] + severity: WARNING + message: >- + The environment variable `ACTIONS_ALLOW_UNSECURE_COMMANDS` grants this workflow permissions + to use the `set-env` and `add-path` commands. There is a vulnerability in these commands + that could result in environment variables being modified by an attacker. Depending on the + use of the environment variable, this could enable an attacker to, at worst, + modify the system path to run a different command than intended, resulting in arbitrary + code execution. This could result in stolen code or secrets. + Don't use `ACTIONS_ALLOW_UNSECURE_COMMANDS`. Instead, use Environment Files. See + https://github.com/actions/toolkit/blob/main/docs/commands.md#environment-files for + more information. + metadata: + cwe: + - 'CWE-749: Exposed Dangerous Method or Function' + owasp: 'A06:2017 - Security Misconfiguration' + references: + - https://github.blog/changelog/2020-10-01-github-actions-deprecating-set-env-and-add-path-commands/ + - https://github.com/actions/toolkit/security/advisories/GHSA-mfwh-5m23-j46w + - https://github.com/actions/toolkit/blob/main/docs/commands.md#environment-files + category: security + technology: + - github-actions + subcategory: + - vuln + likelihood: LOW + impact: MEDIUM + confidence: MEDIUM + patterns: + - pattern-either: + - patterns: + - pattern-inside: '{env: ...}' + - pattern: 'ACTIONS_ALLOW_UNSECURE_COMMANDS: true' +- id: yaml.github-actions.security.curl-eval.curl-eval + languages: + - yaml + message: Data is being eval'd from a `curl` command. An attacker with control of the server in the `curl` + command could inject malicious code into the `eval`, resulting in a system comrpomise. Avoid eval'ing + untrusted data if you can. If you must do this, consider checking the SHA sum of the content returned + by the server to verify its integrity. + metadata: + category: security + cwe: + - "CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')" + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + references: + - https://docs.github.com/en/actions/learn-github-actions/security-hardening-for-github-actions#understanding-the-risk-of-script-injections + technology: + - github-actions + - bash + - curl + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH + confidence: LOW + patterns: + - pattern-inside: 'steps: [...]' + - pattern-inside: | + - run: ... + ... + - pattern: 'run: $SHELL' + - metavariable-pattern: + language: bash + metavariable: $SHELL + patterns: + - pattern: | + $DATA=<... curl ...> + ... + eval <... $DATA ...> + severity: ERROR +- id: yaml.github-actions.security.github-script-injection.github-script-injection + languages: + - yaml + message: >- + Using variable interpolation `${{...}}` with `github` context data in a `actions/github-script`'s + `script:` step could allow an attacker to + inject their own code into the runner. This would allow them to steal secrets and code. `github` context + data can have + arbitrary user input and should be treated as untrusted. Instead, use an intermediate environment + variable with `env:` + to store the data and use the environment variable in the `run:` script. Be sure to use double-quotes + the environment + variable, like this: "$ENVVAR". + metadata: + category: security + cwe: + - "CWE-94: Improper Control of Generation of Code ('Code Injection')" + owasp: + - A03:2021 - Injection + references: + - https://docs.github.com/en/actions/learn-github-actions/security-hardening-for-github-actions#understanding-the-risk-of-script-injections + - https://securitylab.github.com/research/github-actions-untrusted-input/ + - https://github.com/actions/github-script + technology: + - github-actions + cwe2022-top25: true + subcategory: + - vuln + likelihood: HIGH + impact: HIGH + confidence: HIGH + patterns: + - pattern-inside: 'steps: [...]' + - pattern-inside: | + uses: $ACTION + ... + - pattern-inside: | + with: + ... + script: ... + ... + - pattern: 'script: $SHELL' + - metavariable-regex: + metavariable: $ACTION + regex: actions/github-script@.* + - metavariable-pattern: + language: generic + metavariable: $SHELL + patterns: + - pattern-either: + - pattern: ${{ github.event.issue.title }} + - pattern: ${{ github.event.issue.body }} + - pattern: ${{ github.event.pull_request.title }} + - pattern: ${{ github.event.pull_request.body }} + - pattern: ${{ github.event.comment.body }} + - pattern: ${{ github.event.review.body }} + - pattern: ${{ github.event.review_comment.body }} + - pattern: ${{ github.event.pages. ... .page_name}} + - pattern: ${{ github.event.head_commit.message }} + - pattern: ${{ github.event.head_commit.author.email }} + - pattern: ${{ github.event.head_commit.author.name }} + - pattern: ${{ github.event.commits ... .author.email }} + - pattern: ${{ github.event.commits ... .author.name }} + - pattern: ${{ github.event.pull_request.head.ref }} + - pattern: ${{ github.event.pull_request.head.label }} + - pattern: ${{ github.event.pull_request.head.repo.default_branch }} + - pattern: ${{ github.head_ref }} + - pattern: ${{ github.event.inputs ... }} + severity: ERROR +- id: yaml.github-actions.security.pull-request-target-code-checkout.pull-request-target-code-checkout + languages: + - yaml + message: >- + This GitHub Actions workflow file uses `pull_request_target` and checks out code + from the incoming pull request. When using `pull_request_target`, the Action + runs in the context of the target repository, which includes access to all repository + secrets. Normally, this is safe because the Action only runs code from the target + repository, not the incoming PR. However, by checking out the incoming PR code, you're now using + the incoming code for the rest of the action. You may be inadvertently executing arbitrary code + from the incoming PR with access to repository secrets, which would let an attacker steal repository + secrets. + This normally happens by running build scripts (e.g., `npm build` and `make`) or dependency installation + scripts (e.g., `python setup.py install`). + Audit your workflow file to make sure no code from the incoming PR is executed. + Please see https://securitylab.github.com/research/github-actions-preventing-pwn-requests/ for additional + mitigations. + metadata: + category: security + owasp: + - A01:2021 - Broken Access Control + cwe: + - 'CWE-913: Improper Control of Dynamically-Managed Code Resources' + references: + - https://securitylab.github.com/research/github-actions-preventing-pwn-requests/ + - https://github.com/justinsteven/advisories/blob/master/2021_github_actions_checkspelling_token_leak_via_advice_symlink.md + technology: + - github-actions + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + patterns: + - pattern-either: + - pattern-inside: | + on: + ... + pull_request_target: ... + ... + ... + - pattern-inside: | + on: [..., pull_request_target, ...] + ... + - pattern-inside: | + on: pull_request_target + ... + - pattern-inside: | + jobs: + ... + $JOBNAME: + ... + steps: + ... + - pattern: | + ... + uses: "$ACTION" + with: + ... + ref: $EXPR + - metavariable-regex: + metavariable: $ACTION + regex: actions/checkout@.* + - metavariable-pattern: + language: generic + metavariable: $EXPR + patterns: + - pattern: ${{ github.event.pull_request ... }} + severity: WARNING +- id: yaml.github-actions.security.run-shell-injection.run-shell-injection + languages: + - yaml + message: 'Using variable interpolation `${{...}}` with `github` context data in a `run:` step could + allow an attacker to inject their own code into the runner. This would allow them to steal secrets + and code. `github` context data can have arbitrary user input and should be treated as untrusted. + Instead, use an intermediate environment variable with `env:` to store the data and use the environment + variable in the `run:` script. Be sure to use double-quotes the environment variable, like this: "$ENVVAR".' + metadata: + category: security + cwe: + - "CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')" + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + references: + - https://docs.github.com/en/actions/learn-github-actions/security-hardening-for-github-actions#understanding-the-risk-of-script-injections + - https://securitylab.github.com/research/github-actions-untrusted-input/ + technology: + - github-actions + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: HIGH + impact: HIGH + confidence: HIGH + patterns: + - pattern-inside: 'steps: [...]' + - pattern-inside: | + - run: ... + ... + - pattern: 'run: $SHELL' + - metavariable-pattern: + language: generic + metavariable: $SHELL + patterns: + - pattern-either: + - pattern: ${{ github.event.issue.title }} + - pattern: ${{ github.event.issue.body }} + - pattern: ${{ github.event.pull_request.title }} + - pattern: ${{ github.event.pull_request.body }} + - pattern: ${{ github.event.comment.body }} + - pattern: ${{ github.event.review.body }} + - pattern: ${{ github.event.review_comment.body }} + - pattern: ${{ github.event.pages. ... .page_name}} + - pattern: ${{ github.event.head_commit.message }} + - pattern: ${{ github.event.head_commit.author.email }} + - pattern: ${{ github.event.head_commit.author.name }} + - pattern: ${{ github.event.commits ... .author.email }} + - pattern: ${{ github.event.commits ... .author.name }} + - pattern: ${{ github.event.pull_request.head.ref }} + - pattern: ${{ github.event.pull_request.head.label }} + - pattern: ${{ github.event.pull_request.head.repo.default_branch }} + - pattern: ${{ github.head_ref }} + - pattern: ${{ github.event.inputs ... }} + severity: ERROR + +- id: yaml.github-actions.security.third-party-action-not-pinned-to-commit-sha.third-party-action-not-pinned-to-commit-sha + patterns: + - pattern-inside: "{steps: ...}" + - pattern: | + uses: "$USES" + - metavariable-pattern: + metavariable: $USES + language: generic + patterns: + # Locally-defined action + - pattern-not-regex: "^[.]/" + # GitHub-owned action + - pattern-not-regex: "^actions/" + # GitHub-owned action + - pattern-not-regex: "^github/" + # Action with pinned commit SHA + - pattern-not-regex: "@[0-9a-f]{40}$" + # Docker action with pinned image digest + - pattern-not-regex: "^docker://.*@sha256:[0-9a-f]{64}$" + message: >- + An action sourced from a third-party repository on GitHub is not pinned + to a full length commit SHA. Pinning an action to a full length commit SHA + is currently the only way to use an action as an immutable release. Pinning + to a particular SHA helps mitigate the risk of a bad actor adding a backdoor + to the action's repository, as they would need to generate a SHA-1 collision + for a valid Git object payload. + languages: + - yaml + severity: WARNING + metadata: + cwe: + - "CWE-1357: Reliance on Insufficiently Trustworthy Component" + - "CWE-353: Missing Support for Integrity Check" + owasp: A06:2021 - Vulnerable and Outdated Components + references: + - https://owasp.org/Top10/A06_2021-Vulnerable_and_Outdated_Components + - https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions#using-third-party-actions + category: security + technology: + - github-actions + subcategory: + - vuln + likelihood: LOW + impact: LOW + confidence: HIGH +- id: yaml.github-actions.security.workflow-run-target-code-checkout.workflow-run-target-code-checkout + languages: + - yaml + message: >- + This GitHub Actions workflow file uses `workflow_run` and checks out code + from the incoming pull request. When using `workflow_run`, the Action + runs in the context of the target repository, which includes access to all repository + secrets. Normally, this is safe because the Action only runs code from the target + repository, not the incoming PR. However, by checking out the incoming PR code, you're now using + the incoming code for the rest of the action. You may be inadvertently executing arbitrary code + from the incoming PR with access to repository secrets, which would let an attacker steal repository secrets. + This normally happens by running build scripts (e.g., `npm build` and `make`) or dependency installation + scripts (e.g., `python setup.py install`). + Audit your workflow file to make sure no code from the incoming PR is executed. + Please see https://securitylab.github.com/research/github-actions-preventing-pwn-requests/ for additional + mitigations. + metadata: + category: security + owasp: "A01:2017 - Injection" + cwe: "CWE-913: Improper Control of Dynamically-Managed Code Resources" + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + subcategory: + - vuln + references: + - https://securitylab.github.com/research/github-actions-preventing-pwn-requests/ + - https://github.com/justinsteven/advisories/blob/master/2021_github_actions_checkspelling_token_leak_via_advice_symlink.md + - https://www.legitsecurity.com/blog/github-privilege-escalation-vulnerability + technology: + - github-actions + patterns: + - pattern-inside: | + on: + ... + workflow_run: ... + ... + ... + - pattern-inside: | + jobs: + ... + $JOBNAME: + ... + steps: + ... + - pattern: | + ... + uses: "$ACTION" + with: + ... + ref: $EXPR + - metavariable-regex: + metavariable: $ACTION + regex: actions/checkout@.* + - metavariable-pattern: + language: generic + metavariable: $EXPR + patterns: + - pattern: ${{ github.event.workflow_run ... }} + severity: WARNING + +- id: yaml.github-actions.semgrep-configuration.semgrep-github-action-push-without-branches.semgrep-github-action-push-without-branches + message: The 'branches' field (in the push event configuration) contains no + branches. This causes all branches to be scanned and may result in + unneccessary duplicate findings across the entire codebase. + severity: WARNING + languages: + - yaml + paths: + include: + - ".github/workflows/semgrep.yml" + - "*.test.yml" + patterns: + - pattern-either: + - pattern: | + on: [..., push, ...] + ... + - pattern: | + on: push + ... + - pattern: | + on: + ... + push: "" + ... + ... + - pattern: | + on: + ... + push: {} + ... + ... + - patterns: + - pattern-inside: | + on: + ... + push: ... + ... + ... + - pattern-either: + - pattern: | + branches: "" + - pattern: | + branches: [] + metadata: + category: correctness + technology: + - github-action +- id: yaml.gitlab.correctness.changes-with-when-never.changes-with-when-never + pattern: | + - changes: + - ... + when: never + message: >- + This Gitlab CI YAML will never run on default branches due to a `changes` rule with `when:never`. + To fix this, make sure the triggering event is a push event. You can do this with `if: '$CI_PIPELINE_SOURCE == "push"'`. + See https://docs.gitlab.com/ee/ci/yaml/index.html#ruleschanges + metadata: + category: correctness + technology: + - gitlab + - gitlab-ci + languages: [yaml] + severity: WARNING + +- id: yaml.kubernetes.best-practice.no-fractional-cpu-limits.no-fractional-cpu-limits + patterns: + - pattern-inside: | + limits: + ... + - pattern: | + cpu: $CPU_LIMIT + - metavariable-regex: + metavariable: $CPU_LIMIT + regex: \d{0,3}m + fix: "cpu: 1000m" + message: >- + When you set a fractional CPU limit on a container, + the CPU cycles available will be throttled, + even though most nodes can handle processes + alternating between using 100% of the CPU. + severity: WARNING + languages: [yaml] + metadata: + category: best-practice + technology: + - kubernetes +- id: yaml.kubernetes.security.allow-privilege-escalation-no-securitycontext.allow-privilege-escalation-no-securitycontext + patterns: + - pattern-inside: | + containers: + ... + - pattern-inside: | + - $NAME: $CONTAINER + ... + - pattern: | + image: ... + ... + - pattern-not: | + image: ... + ... + securityContext: + ... + - metavariable-regex: + metavariable: $NAME + regex: "name" + - focus-metavariable: $NAME + fix: | + securityContext: + allowPrivilegeEscalation: false + $NAME + message: >- + In Kubernetes, each pod runs in its own isolated environment with its own + set of security policies. However, certain container images may contain + `setuid` or `setgid` binaries that could allow an attacker to perform + privilege escalation and gain access to sensitive resources. To mitigate + this risk, it's recommended to add a `securityContext` to the container in + the pod, with the parameter `allowPrivilegeEscalation` set to `false`. + This will prevent the container from running any privileged processes and + limit the impact of any potential attacks. + By adding a `securityContext` to your Kubernetes pod, you can help to + ensure that your containerized applications are more secure and less + vulnerable to privilege escalation attacks. + metadata: + cwe: + - 'CWE-732: Incorrect Permission Assignment for Critical Resource' + owasp: + - A05:2021 - Security Misconfiguration + - A06:2017 - Security Misconfiguration + references: + - https://kubernetes.io/docs/concepts/policy/pod-security-policy/#privilege-escalation + - https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ + - https://www.kernel.org/doc/Documentation/prctl/no_new_privs.txt + - https://cheatsheetseries.owasp.org/cheatsheets/Docker_Security_Cheat_Sheet.html#rule-4-add-no-new-privileges-flag + category: security + technology: + - kubernetes + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + languages: [yaml] + severity: WARNING +- id: yaml.kubernetes.security.allow-privilege-escalation-true.allow-privilege-escalation-true + patterns: + - pattern-inside: | + containers: + ... + - pattern-inside: | + - name: $CONTAINER + ... + - pattern-inside: | + image: ... + ... + - pattern-inside: | + securityContext: + ... + - pattern: | + allowPrivilegeEscalation: $TRUE + - metavariable-pattern: + metavariable: $TRUE + pattern: | + true + - focus-metavariable: $TRUE + fix: | + false + message: >- + In Kubernetes, each pod runs in its own isolated environment with its own + set of security policies. However, certain container images may contain + `setuid` or `setgid` binaries that could allow an attacker to perform + privilege escalation and gain access to sensitive resources. To mitigate + this risk, it's recommended to add a `securityContext` to the container in + the pod, with the parameter `allowPrivilegeEscalation` set to `false`. + This will prevent the container from running any privileged processes and + limit the impact of any potential attacks. + In the container `$CONTAINER` this parameter is set to `true` which makes + this container much more vulnerable to privelege escalation attacks. + metadata: + cwe: + - 'CWE-732: Incorrect Permission Assignment for Critical Resource' + owasp: + - A05:2021 - Security Misconfiguration + - A06:2017 - Security Misconfiguration + references: + - https://kubernetes.io/docs/concepts/policy/pod-security-policy/#privilege-escalation + - https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ + - https://www.kernel.org/doc/Documentation/prctl/no_new_privs.txt + - https://cheatsheetseries.owasp.org/cheatsheets/Docker_Security_Cheat_Sheet.html#rule-4-add-no-new-privileges-flag + category: security + technology: + - kubernetes + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + languages: [yaml] + severity: WARNING +- id: yaml.kubernetes.security.allow-privilege-escalation.allow-privilege-escalation + patterns: + - pattern-inside: | + containers: + ... + - pattern-inside: | + - name: $CONTAINER + ... + - pattern: | + image: ... + ... + - pattern-inside: | + image: ... + ... + $SC: + ... + - metavariable-regex: + metavariable: $SC + regex: ^(securityContext)$ + - pattern-not-inside: | + image: ... + ... + securityContext: + ... + allowPrivilegeEscalation: $VAL + - focus-metavariable: $SC + fix: | + securityContext: + allowPrivilegeEscalation: false # + message: >- + In Kubernetes, each pod runs in its own isolated environment with its own + set of security policies. However, certain container images may contain + `setuid` or `setgid` binaries that could allow an attacker to perform + privilege escalation and gain access to sensitive resources. To mitigate + this risk, it's recommended to add a `securityContext` to the container in + the pod, with the parameter `allowPrivilegeEscalation` set to `false`. + This will prevent the container from running any privileged processes and + limit the impact of any potential attacks. + By adding the `allowPrivilegeEscalation` parameter to your the + `securityContext`, you can help to + ensure that your containerized applications are more secure and less + vulnerable to privilege escalation attacks. + metadata: + cwe: + - 'CWE-732: Incorrect Permission Assignment for Critical Resource' + owasp: + - A05:2021 - Security Misconfiguration + - A06:2017 - Security Misconfiguration + references: + - https://kubernetes.io/docs/concepts/policy/pod-security-policy/#privilege-escalation + - https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ + - https://www.kernel.org/doc/Documentation/prctl/no_new_privs.txt + - https://cheatsheetseries.owasp.org/cheatsheets/Docker_Security_Cheat_Sheet.html#rule-4-add-no-new-privileges-flag + category: security + technology: + - kubernetes + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + languages: [yaml] + severity: WARNING +- id: yaml.kubernetes.security.env.flask-debugging-enabled.flask-debugging-enabled + languages: [yaml] + severity: WARNING + message: >- + Do not set FLASK_ENV to "development" since that sets `debug=True` in Flask. + Use "dev" or a similar term instead. + metadata: + owasp: 'A06:2017 - Security Misconfiguration' + cwe: + - 'CWE-489: Active Debug Code' + references: + - https://flask.palletsprojects.com/en/2.0.x/debugging/ + - https://flask.palletsprojects.com/en/2.0.x/config/#ENV + category: security + technology: + - kubernetes + - flask + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + patterns: + - pattern-inside: | + env: [...] + - pattern: | + {name: FLASK_ENV, value: "development"} + fix-regex: + regex: development + replacement: dev +- id: yaml.kubernetes.security.exposing-docker-socket-hostpath.exposing-docker-socket-hostpath + patterns: + - pattern-inside: | + volumes: + ... + - pattern: | + hostPath: + ... + path: /var/run/docker.sock + message: >- + Exposing host's Docker socket to containers via a volume. The owner of this + socket is root. Giving someone access to it is equivalent to giving + unrestricted root access to your host. Remove 'docker.sock' from hostpath to + prevent this. + metadata: + cwe: + - 'CWE-250: Execution with Unnecessary Privileges' + references: + - https://kubernetes.io/docs/concepts/storage/volumes/#hostpath + - https://kubernetes.io/docs/concepts/policy/pod-security-policy/#volumes-and-file-systems + - https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ + - https://cheatsheetseries.owasp.org/cheatsheets/Docker_Security_Cheat_Sheet.html#rule-1-do-not-expose-the-docker-daemon-socket-even-to-the-containers + category: security + technology: + - kubernetes + subcategory: + - vuln + likelihood: LOW + impact: HIGH + confidence: MEDIUM + languages: [yaml] + severity: WARNING +- id: yaml.kubernetes.security.hostipc-pod.hostipc-pod + patterns: + - pattern-inside: | + spec: + ... + - pattern: | + hostIPC: true + message: >- + Pod is sharing the host IPC namespace. This allows container processes + to communicate with processes on the host which reduces isolation and + bypasses container protection models. Remove the 'hostIPC' key to disable + this functionality. + metadata: + cwe: + - 'CWE-693: Protection Mechanism Failure' + references: + - https://kubernetes.io/docs/concepts/policy/pod-security-policy/#host-namespaces + category: security + technology: + - kubernetes + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + languages: [yaml] + severity: WARNING +- id: yaml.kubernetes.security.hostnetwork-pod.hostnetwork-pod + patterns: + - pattern-inside: | + spec: + ... + - pattern: | + hostNetwork: true + message: >- + Pod may use the node network namespace. This gives the pod access to the + loopback device, services listening on localhost, and could be used to + snoop on network activity of other pods on the same node. Remove the + 'hostNetwork' key to disable this functionality. + metadata: + cwe: + - 'CWE-406: Insufficient Control of Network Message Volume (Network Amplification)' + references: + - https://kubernetes.io/docs/concepts/policy/pod-security-policy/#host-namespaces + category: security + technology: + - kubernetes + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + languages: [yaml] + severity: WARNING +- id: yaml.kubernetes.security.hostpid-pod.hostpid-pod + patterns: + - pattern-inside: | + spec: + ... + - pattern: | + hostPID: true + message: >- + Pod is sharing the host process ID namespace. When paired with ptrace + this can be used to escalate privileges outside of the container. Remove + the 'hostPID' key to disable this functionality. + metadata: + cwe: + - 'CWE-269: Improper Privilege Management' + references: + - https://kubernetes.io/docs/concepts/policy/pod-security-policy/#host-namespaces + category: security + technology: + - kubernetes + owasp: + - A04:2021 - Insecure Design + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + languages: [yaml] + severity: WARNING +- id: yaml.kubernetes.security.legacy-api-clusterrole-excessive-permissions.legacy-api-clusterrole-excessive-permissions + patterns: + - pattern: | + "*" + - pattern-inside: | + resources: $A + ... + - pattern-inside: | + verbs: $A + ... + - pattern-inside: | + - apiGroups: [""] + ... + - pattern-inside: | + apiVersion: rbac.authorization.k8s.io/v1 + ... + - pattern-inside: | + kind: ClusterRole + ... + message: >- + Semgrep detected a Kubernetes core API ClusterRole with excessive permissions. Attaching excessive permissions to a ClusterRole associated with the core namespace allows the V1 API to perform arbitrary actions on arbitrary resources attached to the cluster. Prefer explicit allowlists of verbs/resources when configuring the core API namespace. + languages: + - yaml + severity: WARNING + metadata: + cwe: + - "CWE-269: Improper Privilege Management" + owasp: + - A05:2021 - Security Misconfiguration + - A06:2017 - Security Misconfiguration + references: + - https://kubernetes.io/docs/reference/access-authn-authz/rbac/#role-and-clusterrole + - https://kubernetes.io/docs/concepts/security/rbac-good-practices/#general-good-practice + - https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.28/#api-groups + category: security + technology: + - kubernetes + cwe2021-top25: false + subcategory: + - vuln + likelihood: MEDIUM + impact: HIGH + confidence: HIGH +- id: yaml.kubernetes.security.privileged-container.privileged-container + pattern-either: + - patterns: + - pattern-inside: | + containers: + ... + - pattern: | + image: ... + ... + securityContext: + ... + privileged: true + - patterns: + - pattern-inside: | + spec: + ... + - pattern-not-inside: | + image: ... + ... + - pattern: | + privileged: true + message: >- + Container or pod is running in privileged mode. This grants the + container the equivalent of root capabilities on the host machine. This + can lead to container escapes, privilege escalation, and other security + concerns. Remove the 'privileged' key to disable this capability. + metadata: + cwe: + - 'CWE-250: Execution with Unnecessary Privileges' + references: + - https://kubernetes.io/docs/concepts/policy/pod-security-policy/#privileged + - https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ + - https://cheatsheetseries.owasp.org/cheatsheets/Docker_Security_Cheat_Sheet.html + category: security + technology: + - kubernetes + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + languages: [yaml] + severity: WARNING +- id: yaml.kubernetes.security.run-as-non-root-container-level-missing-security-context.run-as-non-root-container-level-missing-security-context + patterns: + - pattern-inside: | + spec: + ... + containers: + ... + ... + # No runAsNonRoot in Security Context at pod level + - pattern-not-inside: | + spec: + ... + securityContext: + ... + runAsNonRoot: $VAL + ... + # Containers defined + - pattern-inside: | + spec: + ... + containers: + ... + # At least one container in this pod has defined runAsNonRoot + # So a decision is made to secure at container level + - pattern-inside: | + spec: + ... + containers: + ... + - name: $NAME + image: ... + ... + securityContext: + ... + runAsNonRoot: $VALUE + # Capture container image + - pattern: | + - name: $CONTAINER + $IMAGE: $IMAGEVAL + ... + # But missing securityContext + - pattern-not: | + - name: $CONTAINER + image: $IMAGEVAL + ... + securityContext: + ... + - metavariable-regex: + metavariable: $IMAGE + regex: "image" + - focus-metavariable: $IMAGE + fix: | + securityContext: + runAsNonRoot: true + $IMAGE + message: >- + When running containers in Kubernetes, it's important to ensure that they + are properly secured to prevent privilege escalation attacks. + One potential vulnerability is when a container is allowed to run + applications as the root user, which could allow an attacker to gain + access to sensitive resources. To mitigate this risk, it's recommended to + add a `securityContext` to the container, with the parameter `runAsNonRoot` + set to `true`. This will ensure that the container runs as a non-root user, + limiting the damage that could be caused by any potential attacks. By + adding a `securityContext` to the container in your Kubernetes pod, you can + help to ensure that your containerized applications are more secure and + less vulnerable to privilege escalation attacks. + metadata: + references: + - https://kubernetes.io/blog/2016/08/security-best-practices-kubernetes-deployment/ + - https://kubernetes.io/docs/concepts/policy/pod-security-policy/ + - https://cheatsheetseries.owasp.org/cheatsheets/Docker_Security_Cheat_Sheet.html#rule-2-set-a-user + category: security + cwe: + - 'CWE-250: Execution with Unnecessary Privileges' + owasp: + - A05:2021 - Security Misconfiguration + - A06:2017 - Security Misconfiguration + technology: + - kubernetes + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: + - yaml + severity: INFO +- id: yaml.kubernetes.security.run-as-non-root-container-level.run-as-non-root-container-level + patterns: + - pattern-inside: | + spec: + ... + containers: + ... + ... + # No runAsNonRoot in Security Context at pod level + - pattern-not-inside: | + spec: + ... + securityContext: + ... + runAsNonRoot: $VAL + ... + # Containers defined + - pattern-inside: | + spec: + ... + containers: + ... + # At least one container in this pod has defined runAsNonRoot + # So a decision is made to secure at container level + - pattern-inside: | + spec: + ... + containers: + ... + - name: $NAME + image: ... + ... + securityContext: + ... + runAsNonRoot: $VALUE + # Capture container security Context + - pattern: | + - name: $CONTAINER + image: ... + ... + $SC: + ... + - metavariable-regex: + metavariable: $SC + regex: ^(securityContext)$ + # But missing runAsNonRoot + - pattern-not: | + - name: $CONTAINER + image: ... + ... + securityContext: + ... + runAsNonRoot: $VALUE + - focus-metavariable: $SC + fix: | + $SC: + runAsNonRoot: true # + message: >- + When running containers in Kubernetes, it's important to ensure that they + are properly secured to prevent privilege escalation attacks. + One potential vulnerability is when a container is allowed to run + applications as the root user, which could allow an attacker to gain + access to sensitive resources. To mitigate this risk, it's recommended to + add a `securityContext` to the container, with the parameter `runAsNonRoot` + set to `true`. This will ensure that the container runs as a non-root user, + limiting the damage that could be caused by any potential attacks. By + adding a `securityContext` to the container in your Kubernetes pod, you can + help to ensure that your containerized applications are more secure and + less vulnerable to privilege escalation attacks. + metadata: + references: + - https://kubernetes.io/blog/2016/08/security-best-practices-kubernetes-deployment/ + - https://kubernetes.io/docs/concepts/policy/pod-security-policy/ + - https://cheatsheetseries.owasp.org/cheatsheets/Docker_Security_Cheat_Sheet.html#rule-2-set-a-user + category: security + cwe: + - 'CWE-250: Execution with Unnecessary Privileges' + owasp: + - A05:2021 - Security Misconfiguration + - A06:2017 - Security Misconfiguration + technology: + - kubernetes + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: + - yaml + severity: INFO +- id: yaml.kubernetes.security.run-as-non-root-security-context-pod-level.run-as-non-root-security-context-pod-level + patterns: + # Pod Security Context + - pattern-inside: | + spec: + ... + $SC: + ... + ... + - metavariable-regex: + metavariable: $SC + regex: ^(securityContext)$ + # Pod Security Context does not contain runAsNonRoot + - pattern-not-inside: | + spec: + ... + securityContext: + runAsNonRoot: $VAL + ... + # Containers defined + - pattern-inside: | + $SPEC: + ... + containers: + ... + # Security Context of all containers in this pod are missing runAsNonRoot + # So no decision is made to secure at container level in other containers + - pattern-not-inside: | + $SPEC: + ... + containers: + ... + - name: $NAME + image: ... + ... + securityContext: + ... + runAsNonRoot: $VALUE + - focus-metavariable: $SC + fix: | + $SC: + runAsNonRoot: true # + message: >- + When running containers in Kubernetes, it's important to ensure that they + are properly secured to prevent privilege escalation attacks. + One potential vulnerability is when a container is allowed to run + applications as the root user, which could allow an attacker to gain + access to sensitive resources. To mitigate this risk, it's recommended to + add a `securityContext` to the container, with the parameter `runAsNonRoot` + set to `true`. This will ensure that the container runs as a non-root user, + limiting the damage that could be caused by any potential attacks. By + adding a `securityContext` to the container in your Kubernetes pod, you can + help to ensure that your containerized applications are more secure and + less vulnerable to privilege escalation attacks. + metadata: + references: + - https://kubernetes.io/blog/2016/08/security-best-practices-kubernetes-deployment/ + - https://kubernetes.io/docs/concepts/policy/pod-security-policy/ + - https://cheatsheetseries.owasp.org/cheatsheets/Docker_Security_Cheat_Sheet.html#rule-2-set-a-user + category: security + cwe: + - 'CWE-250: Execution with Unnecessary Privileges' + owasp: + - A05:2021 - Security Misconfiguration + - A06:2017 - Security Misconfiguration + technology: + - kubernetes + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: + - yaml + severity: INFO +- id: yaml.kubernetes.security.run-as-non-root-unsafe-value.run-as-non-root-unsafe-value + patterns: + - pattern-either: + # Pod Security Context + - pattern: | + spec: + ... + securityContext: + ... + runAsNonRoot: $VALUE + # Container Security Context + - patterns: + - pattern-inside: | + containers: + ... + - pattern: | + image: ... + ... + securityContext: + ... + runAsNonRoot: $VALUE + - metavariable-pattern: + metavariable: $VALUE + pattern: | + false + - focus-metavariable: $VALUE + fix: | + true + message: >- + When running containers in Kubernetes, it's important to ensure that they + are properly secured to prevent privilege escalation attacks. + One potential vulnerability is when a container is allowed to run + applications as the root user, which could allow an attacker to gain + access to sensitive resources. To mitigate this risk, it's recommended to + add a `securityContext` to the container, with the parameter `runAsNonRoot` + set to `true`. This will ensure that the container runs as a non-root user, + limiting the damage that could be caused by any potential attacks. By + adding a `securityContext` to the container in your Kubernetes pod, you can + help to ensure that your containerized applications are more secure and + less vulnerable to privilege escalation attacks. + metadata: + references: + - https://kubernetes.io/blog/2016/08/security-best-practices-kubernetes-deployment/ + - https://kubernetes.io/docs/concepts/policy/pod-security-policy/ + - https://cheatsheetseries.owasp.org/cheatsheets/Docker_Security_Cheat_Sheet.html#rule-2-set-a-user + cwe: + - 'CWE-250: Execution with Unnecessary Privileges' + owasp: + - A05:2021 - Security Misconfiguration + - A06:2017 - Security Misconfiguration + category: security + technology: + - kubernetes + subcategory: + - audit + likelihood: MEDIUM + impact: HIGH + confidence: MEDIUM + languages: [yaml] + severity: INFO +- id: yaml.kubernetes.security.run-as-non-root.run-as-non-root + patterns: + # Capture spec + - pattern-inside: | + $SPEC: + ... + containers: + ... + ... + - metavariable-regex: + metavariable: $SPEC + regex: ^(spec)$ + # No Pod Security Context + - pattern-not-inside: | + spec: + ... + securityContext: + ... + ... + # Containers defined + - pattern-inside: | + $SPEC: + ... + containers: + ... + # Security Context of all containers in this pod are missing runAsNonRoot + # So no decision is made to secure at container level in other containers + - pattern-not-inside: | + $SPEC: + ... + containers: + ... + - name: $NAME + image: ... + ... + securityContext: + ... + runAsNonRoot: $VALUE + - focus-metavariable: $SPEC + fix: | + $SPEC: + securityContext: + runAsNonRoot: true # + message: >- + When running containers in Kubernetes, it's important to ensure that they + are properly secured to prevent privilege escalation attacks. + One potential vulnerability is when a container is allowed to run + applications as the root user, which could allow an attacker to gain + access to sensitive resources. To mitigate this risk, it's recommended to + add a `securityContext` to the container, with the parameter `runAsNonRoot` + set to `true`. This will ensure that the container runs as a non-root user, + limiting the damage that could be caused by any potential attacks. By + adding a `securityContext` to the container in your Kubernetes pod, you can + help to ensure that your containerized applications are more secure and + less vulnerable to privilege escalation attacks. + metadata: + references: + - https://kubernetes.io/blog/2016/08/security-best-practices-kubernetes-deployment/ + - https://kubernetes.io/docs/concepts/policy/pod-security-policy/ + - https://cheatsheetseries.owasp.org/cheatsheets/Docker_Security_Cheat_Sheet.html#rule-2-set-a-user + category: security + cwe: + - 'CWE-250: Execution with Unnecessary Privileges' + owasp: + - A05:2021 - Security Misconfiguration + - A06:2017 - Security Misconfiguration + technology: + - kubernetes + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: + - yaml + severity: INFO +- id: yaml.kubernetes.security.seccomp-confinement-disabled.seccomp-confinement-disabled + patterns: + - pattern-inside: | + containers: + ... + - pattern: | + image: ... + ... + securityContext: + ... + seccompProfile: unconfined + message: >- + Container is explicitly disabling seccomp confinement. This runs the + service in an unrestricted state. Remove 'seccompProfile: unconfined' to + prevent this. + metadata: + cwe: + - 'CWE-284: Improper Access Control' + references: + - https://kubernetes.io/docs/concepts/policy/pod-security-policy/#seccomp + - https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ + category: security + technology: + - kubernetes + owasp: + - A05:2017 - Broken Access Control + - A01:2021 - Broken Access Control + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + languages: [yaml] + severity: WARNING +- id: yaml.kubernetes.security.secrets-in-config-file.secrets-in-config-file + patterns: + - pattern: | + $KEY: $VALUE + - pattern-inside: | + data: ... + - pattern-inside: | + kind: Secret + ... + - metavariable-regex: + metavariable: $VALUE + regex: (?i)^[aA-zZ0-9+/]+={0,2}$ + - metavariable-analysis: + analyzer: entropy + metavariable: $VALUE + message: >- + Secrets ($VALUE) should not be stored in infrastructure as code files. Use an alternative such as + Bitnami Sealed Secrets or KSOPS to encrypt Kubernetes Secrets. + metadata: + cwe: + - 'CWE-798: Use of Hard-coded Credentials' + category: security + technology: + - kubernetes + license: Commons Clause License Condition v1.0[LGPL-2.1-only] + references: + - https://kubernetes.io/docs/concepts/configuration/secret/ + - https://media.defense.gov/2021/Aug/03/2002820425/-1/-1/0/CTR_Kubernetes_Hardening_Guidance_1.1_20220315.PDF + - https://docs.gitlab.com/ee/user/clusters/agent/gitops/secrets_management.html + - https://www.cncf.io/blog/2021/04/22/revealing-the-secrets-of-kubernetes-secrets/ + - https://github.com/bitnami-labs/sealed-secrets + - https://www.cncf.io/blog/2022/01/25/secrets-management-essential-when-using-kubernetes/ + - https://blog.oddbit.com/post/2021-03-09-getting-started-with-ksops/ + owasp: + - A07:2021 - Identification and Authentication Failures + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: LOW + impact: MEDIUM + confidence: MEDIUM + languages: [yaml] + severity: WARNING +- id: yaml.kubernetes.security.skip-tls-verify-cluster.skip-tls-verify-cluster + pattern: | + cluster: + ... + insecure-skip-tls-verify: true + message: >- + Cluster is disabling TLS certificate verification when communicating with + the server. This makes your HTTPS connections insecure. Remove the + 'insecure-skip-tls-verify: true' key to secure communication. + metadata: + cwe: + - 'CWE-319: Cleartext Transmission of Sensitive Information' + references: + - https://kubernetes.io/docs/reference/config-api/client-authentication.v1beta1/#client-authentication-k8s-io-v1beta1-Cluster + category: security + technology: + - kubernetes + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + languages: [yaml] + severity: WARNING +- id: yaml.kubernetes.security.skip-tls-verify-service.skip-tls-verify-service + pattern: | + spec: + ... + insecureSkipTLSVerify: true + message: >- + Service is disabling TLS certificate verification when communicating with + the server. This makes your HTTPS connections insecure. Remove the + 'insecureSkipTLSVerify: true' key to secure communication. + metadata: + cwe: + - 'CWE-319: Cleartext Transmission of Sensitive Information' + references: + - https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.20/#apiservice-v1-apiregistration-k8s-io + category: security + technology: + - kubernetes + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + languages: [yaml] + severity: WARNING +- id: yaml.kubernetes.security.writable-filesystem-container.writable-filesystem-container + patterns: + - pattern-inside: | + containers: + ... + - pattern-inside: | + - name: $CONTAINER + ... + - pattern: | + image: ... + ... + - pattern-not: | + image: ... + ... + securityContext: + ... + readOnlyRootFilesystem: true + - focus-metavariable: $CONTAINER + message: >- + Container $CONTAINER is running with a writable root filesystem. This may allow + malicious applications to download and run additional payloads, or modify + container files. If an application inside a container has to save something + temporarily consider using a tmpfs. Add 'readOnlyRootFilesystem: true' to this + container to prevent this. + metadata: + cwe: + - 'CWE-732: Incorrect Permission Assignment for Critical Resource' + owasp: + - A05:2021 - Security Misconfiguration + - A06:2017 - Security Misconfiguration + references: + - https://kubernetes.io/docs/concepts/policy/pod-security-policy/#volumes-and-file-systems + - https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ + - https://blog.atomist.com/security-of-docker-kubernetes/ + - https://cheatsheetseries.owasp.org/cheatsheets/Docker_Security_Cheat_Sheet.html#rule-8-set-filesystem-and-volumes-to-read-only + category: security + technology: + - kubernetes + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + languages: [yaml] + severity: WARNING +- id: yaml.openapi.security.api-key-in-query-parameter.api-key-in-query-parameter + languages: [yaml] + message: >- + The $SECURITY_SCHEME security scheme passes an API key in a query parameter. + API keys should not be passed as query parameters in security schemes. + Pass the API key in the header or body. + If using a query parameter is necessary, ensure that the API key is tightly scoped and short lived. + severity: WARNING + patterns: + - pattern-inside: | + openapi: $VERSION + ... + components: + ... + securitySchemes: + ... + - metavariable-regex: + metavariable: $VERSION + regex: 3.* + - pattern: | + $SECURITY_SCHEME: + ... + type: apiKey + ... + in: query + + metadata: + category: security + subcategory: + - vuln + technology: + - openapi + likelihood: MEDIUM + impact: HIGH + confidence: LOW + cwe: 'CWE-598: Use of GET Request Method With Sensitive Query Strings' + owasp: + - 'A04:2021 Insecure Design' + - 'A07:2021 Identification and Authentication Failures' + references: + - https://datatracker.ietf.org/doc/html/rfc6749 + - https://cwe.mitre.org/data/definitions/598.html + - https://owasp.org/Top10/A04_2021-Insecure_Design/ + - https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures/ +- id: yaml.openapi.security.use-of-basic-authentication.use-of-basic-authentication + languages: [yaml] + message: >- + Basic authentication is considered weak and should be avoided. + Use a different authentication scheme, such of OAuth2, OpenID Connect, or mTLS. + severity: ERROR + patterns: + - pattern-inside: | + openapi: $VERSION + ... + components: + ... + securitySchemes: + ... + $SCHEME: + ... + - metavariable-regex: + metavariable: $VERSION + regex: 3.* + - pattern: | + type: http + ... + scheme: basic + metadata: + category: security + subcategory: + - vuln + technology: + - openapi + likelihood: MEDIUM + impact: HIGH + confidence: HIGH + cwe: 'CWE-287: Improper Authentication' + owasp: + - 'A04:2021 Insecure Design' + - 'A07:2021 Identification and Authentication Failures' + references: + - https://cwe.mitre.org/data/definitions/287.html + - https://owasp.org/Top10/A04_2021-Insecure_Design/ + - https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures/ + +- fix: bash + id: lang-consistency-bash + languages: + - yaml + message: Found '$X' in language config which diverges from semgrep.dev normalization. + Please use 'bash' instead. + metadata: + category: correctness + technology: + - semgrep + patterns: + - pattern: $X + - pattern-inside: 'languages: ...' + - metavariable-regex: + metavariable: $X + regex: ^(sh)$ + severity: WARNING +- fix: cpp + id: lang-consistency-cpp + languages: + - yaml + message: Found '$X' in language config which diverges from semgrep.dev normalization. + Please use 'cpp' instead. + metadata: + category: correctness + technology: + - semgrep + patterns: + - pattern: $X + - pattern-inside: 'languages: ...' + - metavariable-regex: + metavariable: $X + regex: ^(c\+\+)$ + severity: WARNING +- fix: csharp + id: lang-consistency-csharp + languages: + - yaml + message: Found '$X' in language config which diverges from semgrep.dev normalization. + Please use 'csharp' instead. + metadata: + category: correctness + technology: + - semgrep + patterns: + - pattern: $X + - pattern-inside: 'languages: ...' + - metavariable-regex: + metavariable: $X + regex: ^(c\#)$ + severity: WARNING +- fix: dockerfile + id: lang-consistency-dockerfile + languages: + - yaml + message: Found '$X' in language config which diverges from semgrep.dev normalization. + Please use 'dockerfile' instead. + metadata: + category: correctness + technology: + - semgrep + patterns: + - pattern: $X + - pattern-inside: 'languages: ...' + - metavariable-regex: + metavariable: $X + regex: ^(docker)$ + severity: WARNING +- fix: elixir + id: lang-consistency-elixir + languages: + - yaml + message: Found '$X' in language config which diverges from semgrep.dev normalization. + Please use 'elixir' instead. + metadata: + category: correctness + technology: + - semgrep + patterns: + - pattern: $X + - pattern-inside: 'languages: ...' + - metavariable-regex: + metavariable: $X + regex: ^(ex)$ + severity: WARNING +- fix: go + id: lang-consistency-go + languages: + - yaml + message: Found '$X' in language config which diverges from semgrep.dev normalization. + Please use 'go' instead. + metadata: + category: correctness + technology: + - semgrep + patterns: + - pattern: $X + - pattern-inside: 'languages: ...' + - metavariable-regex: + metavariable: $X + regex: ^(golang)$ + severity: WARNING +- fix: hcl + id: lang-consistency-hcl + languages: + - yaml + message: Found '$X' in language config which diverges from semgrep.dev normalization. + Please use 'hcl' instead. + metadata: + category: correctness + technology: + - semgrep + patterns: + - pattern: $X + - pattern-inside: 'languages: ...' + - metavariable-regex: + metavariable: $X + regex: ^(tf|terraform)$ + severity: WARNING +- fix: js + id: lang-consistency-js + languages: + - yaml + message: Found '$X' in language config which diverges from semgrep.dev normalization. + Please use 'js' instead. + metadata: + category: correctness + technology: + - semgrep + patterns: + - pattern: $X + - pattern-inside: 'languages: ...' + - metavariable-regex: + metavariable: $X + regex: ^(javascript)$ + severity: WARNING +- fix: kotlin + id: lang-consistency-kotlin + languages: + - yaml + message: Found '$X' in language config which diverges from semgrep.dev normalization. + Please use 'kotlin' instead. + metadata: + category: correctness + technology: + - semgrep + patterns: + - pattern: $X + - pattern-inside: 'languages: ...' + - metavariable-regex: + metavariable: $X + regex: ^(kt)$ + severity: WARNING +- fix: python + id: lang-consistency-python + languages: + - yaml + message: Found '$X' in language config which diverges from semgrep.dev normalization. + Please use 'python' instead. + metadata: + category: correctness + technology: + - semgrep + patterns: + - pattern: $X + - pattern-inside: 'languages: ...' + - metavariable-regex: + metavariable: $X + regex: ^(py)$ + severity: WARNING +- fix: regex + id: lang-consistency-regex + languages: + - yaml + message: Found '$X' in language config which diverges from semgrep.dev normalization. + Please use 'regex' instead. + metadata: + category: correctness + technology: + - semgrep + patterns: + - pattern: $X + - pattern-inside: 'languages: ...' + - metavariable-regex: + metavariable: $X + regex: ^(none)$ + severity: WARNING +- fix: solidity + id: lang-consistency-solidity + languages: + - yaml + message: Found '$X' in language config which diverges from semgrep.dev normalization. + Please use 'solidity' instead. + metadata: + category: correctness + technology: + - semgrep + patterns: + - pattern: $X + - pattern-inside: 'languages: ...' + - metavariable-regex: + metavariable: $X + regex: ^(sol)$ + severity: WARNING +- fix: ts + id: lang-consistency-ts + languages: + - yaml + message: Found '$X' in language config which diverges from semgrep.dev normalization. + Please use 'ts' instead. + metadata: + category: correctness + technology: + - semgrep + patterns: + - pattern: $X + - pattern-inside: 'languages: ...' + - metavariable-regex: + metavariable: $X + regex: ^(typescript)$ + severity: WARNING +- id: yaml.semgrep.duplicate-id.duplicate-id + message: >- + The 'id' field $X was used multiple times. + The 'id' field needs to be unique. + severity: ERROR + languages: [yaml] + patterns: + - pattern-inside: "rules: [..., $RULE, ...]" + # nosemgrep: yaml.semgrep.slow-pattern-top-ellipsis + - pattern-inside: | + ... + - id: $X + ... + ... + - id: $X + ... + ... + - pattern: | + id: $X + metadata: + category: correctness + technology: + - semgrep +- id: yaml.semgrep.duplicate-pattern.duplicate-pattern + message: >- + Two identical pattern clauses were detected. + This will cause Semgrep to run the same pattern twice. + Remove one of the duplicate pattern clauses. + severity: ERROR + languages: [yaml] + patterns: + - pattern-inside: "rules: [..., $RULE, ...]" + - pattern-inside: | + - pattern: $X + ... + - pattern: $X + ... + - pattern: | + pattern: $X + metadata: + category: correctness + technology: + - semgrep +- id: yaml.semgrep.empty-message.empty-message + message: >- + This rule has an empty message field. + Consider adding a message field that communicates why this + rule is an issue and how to fix it. This will increase the + chance that the finding gets addressed. + languages: [yaml] + patterns: + - pattern-inside: "rules: [..., $RULE, ...]" + - pattern: | + message: "" + severity: WARNING + metadata: + category: correctness + technology: + - semgrep +- id: yaml.semgrep.interfile-true-under-metadata-and-no-options.interfile-true-under-metadata-and-no-options + message: "`interfile: true` should be under the `options` field, not the + `metadata` field." + languages: + - yaml + severity: WARNING + patterns: + - pattern: | + rules: + - id: $ID + ... + $METADATA: + ... + $INTERFILE: true + ... + ... + - pattern-not-inside: | + rules: + - id: $ID + ... + options: + ... + ... + - metavariable-regex: + metavariable: $INTERFILE + regex: interfile + - metavariable-regex: + metavariable: $METADATA + regex: metadata + - focus-metavariable: $METADATA + fix: | + options: + interfile: true + metadata +- id: yaml.semgrep.interfile-true-under-metadata-and-options-already-present.interfile-true-under-metadata-and-options-already-present + message: >- + `interfile: true` should be under the `options` field, not the `metadata` field. + languages: [yaml] + severity: WARNING + patterns: + - pattern: | + rules: + - id: $ID + ... + $METADATA: + ... + $INTERFILE: true + ... + ... + - pattern-inside: | + rules: + - id: $ID + ... + $OPTIONS: + $FIRST_OPT: $VAL + ... + ... + - pattern-not-inside: | + rules: + - id: $ID + ... + $OPTIONS: + ... + interfile: true + ... + ... + - metavariable-regex: + metavariable: $INTERFILE + regex: interfile + - metavariable-regex: + metavariable: $METADATA + regex: metadata + - metavariable-regex: + metavariable: $OPTIONS + regex: options + - focus-metavariable: $FIRST_OPT + fix: | + interfile: true + $FIRST_OPT +- id: yaml.semgrep.key-indentation.yaml-key-indentation-check + message: "It looks like you have an YAML indentation issue -- instead of writing + `$KEY`, put a space between the hyphen and what comes after! Otherwise, + it reads as a single string. " + languages: + - yaml + severity: WARNING + metadata: + references: + - https://semgrep.dev/docs/contributing/contributing-to-semgrep-rules-repository + category: correctness + technology: + - semgrep + pattern-either: + - patterns: + - pattern-inside: | + rules: ... + - pattern: | + $KEY: >- + $VALUE + - focus-metavariable: $KEY + - metavariable-regex: + metavariable: $KEY + regex: ^-(\w*)$ +- id: yaml.semgrep.message-whitespace.message-whitespace-check + message: >- + It looks like you have an additional space in your rule message, this + can look awkward in the finding output, please remove the additional + whitespace! + languages: + - yaml + severity: WARNING + metadata: + references: + - https://semgrep.dev/docs/contributing/contributing-to-semgrep-rules-repository + category: correctness + technology: + - semgrep + patterns: + - pattern-inside: | + rules: ... + - pattern: | + message: >- + $VALUE + - focus-metavariable: + - $VALUE + - pattern-regex: \w.* + - pattern-regex: \s{2,} + fix-regex: + regex: (?<=\S)\s(\s{1,}) + replacement: " " +- id: yaml.semgrep.metadata-category.metadata-category + message: >- + This Semgrep rule is missing a valid 'category' field in the 'metadata'. + 'category' must be one of 'security', 'correctness', 'best-practice', + 'performance', 'maintainability', or 'portability'. + severity: INFO + patterns: + - pattern-inside: "rules: [..., $RULE, ...]" + - pattern: "id: $RULEID" + - pattern-not-inside: | + - ... + metadata: + ... + category: $CATEGORY + languages: [yaml] + metadata: + category: best-practice + technology: + - semgrep +- id: yaml.semgrep.metadata-confidence-incorrect-value.metadata-confidence-incorrect-value + patterns: + - pattern-inside: | + rules: + ... + - pattern-inside: | + metadata: + ... + category: security + ... + - pattern: | + confidence: $VALUE + - pattern-not: | + confidence: LOW + - pattern-not: | + confidence: MEDIUM + - pattern-not: | + confidence: HIGH + message: >- + Semgrep rule confidence: $VALUE detected, but the value must be LOW, + MEDIUM, or HIGH. For more information visit: + https://semgrep.dev/docs/contributing/contributing-to-semgrep-rules-repository/ + languages: + - yaml + severity: WARNING + metadata: + references: + - https://semgrep.dev/docs/contributing/contributing-to-semgrep-rules-repository/ + category: correctness + technology: + - semgrep +- id: yaml.semgrep.metadata-confidence.metadata-confidence + patterns: + - pattern-inside: | + rules: + ... + - pattern-inside: | + metadata: + ... + category: security + ... + - pattern-not-inside: | + metadata: + ... + confidence: $VALUE + message: >- + This Semgrep rule is missing a valid 'confidence' field in the 'metadata'. + which should be either LOW, MEDIUM, or HIGH. For more information visit + https://semgrep.dev/docs/contributing/contributing-to-semgrep-rules-repository/ + languages: + - yaml + severity: WARNING + metadata: + references: + - https://semgrep.dev/docs/contributing/contributing-to-semgrep-rules-repository + category: correctness + technology: + - semgrep +- id: yaml.semgrep.metadata-cwe.metadata-cwe + message: >- + $...CWE The cwe tag in rule metadata should always be in the format "CWE-000: Title". + severity: ERROR + languages: [yaml] + patterns: + - pattern-inside: "rules: ..." + - pattern-inside: "metadata: ..." + - pattern: "cwe: ..." + - pattern-not-regex: CWE-[\d]+:\s+\w + metadata: + category: best-practice + technology: + - semgrep +- id: yaml.semgrep.metadata-deepsemgrep.metadata-deepsemgrep + patterns: + - pattern-inside: | + rules: + ... + - pattern-inside: | + metadata: + ... + $DEEPSEMGREP: true + ... + - focus-metavariable: $DEEPSEMGREP + - metavariable-regex: + metavariable: $DEEPSEMGREP + regex: ^(deepsemgrep)$ + message: >- + We no longer support `deepsemgrep: true`, please use `interfile:true` + fix-regex: + regex: deepsemgrep + replacement: interfile + languages: + - yaml + severity: WARNING + metadata: + category: correctness + technology: + - semgrep + references: + - https://semgrep.dev/ +- id: yaml.semgrep.metadata-impact-incorrect-value.metadata-impact-incorrect-value + patterns: + - pattern-inside: | + rules: + ... + - pattern-inside: | + metadata: + ... + category: security + ... + - pattern: | + impact: $VALUE + - pattern-not: | + impact: LOW + - pattern-not: | + impact: MEDIUM + - pattern-not: | + impact: HIGH + message: >- + Semgrep rule impact: $VALUE detected, but the value must be LOW, + MEDIUM, or HIGH. For more information visit: + https://semgrep.dev/docs/contributing/contributing-to-semgrep-rules-repository/ + languages: + - yaml + severity: WARNING + metadata: + references: + - https://semgrep.dev/docs/contributing/contributing-to-semgrep-rules-repository/ + category: correctness + technology: + - semgrep +- id: yaml.semgrep.metadata-impact.metadata-impact + patterns: + - pattern-inside: | + rules: + ... + - pattern-inside: | + metadata: + ... + category: security + ... + - pattern-not-inside: | + metadata: + ... + impact: $VALUE + message: >- + This Semgrep rule is missing a valid 'impact' field in the 'metadata'. + which should be either LOW, MEDIUM, or HIGH. For more information visit + https://semgrep.dev/docs/contributing/contributing-to-semgrep-rules-repository/ + languages: + - yaml + severity: WARNING + metadata: + references: + - https://semgrep.dev/docs/writing-rules/rule-syntax/#TODO + category: correctness + technology: + - semgrep +- id: yaml.semgrep.metadata-incorrect-option.metadata-incorrect-option + message: >- + It looks like $KEY is not in the default list of expected options, if this is a new key update this rule + languages: + - yaml + severity: INFO + metadata: + references: + - https://semgrep.dev/docs/contributing/contributing-to-semgrep-rules-repository + category: correctness + technology: + - semgrep + patterns: + - pattern-inside: | + rules: ... + - pattern-inside: | + options: + $A + - focus-metavariable: $A + - pattern: | + $KEY: $VALUE + - metavariable-regex: + metavariable: $KEY + regex: (?!options|constant_propagation|symbolic_propagation|taint_unify_mvars|taint_assume_safe_functions|taint_assume_safe_indexes|taint_assume_safe_comparisons|taint_assume_safe_booleans|taint_assume_safe_numbers|ac_matching|commutative_boolop|flddef_assign|arrow_is_function|let_is_var|go_deeper_expr|go_deeper_stmt|implicit_deep_exprstmt|implicit_ellipsis|xml_singleton_loose_matching|xml_attrs_implicit_ellipsis|xml_children_ordered|generic_engine|generic_multiline|generic_braces|generic_extra_braces|generic_extra_word_characters|generic_caseless|generic_ellipsis_max_span|generic_comment_style|interfile|generic_engine|commutative_compop|taint_focus_on) +- id: yaml.semgrep.metadata-likelihood-incorrect-value.metadata-likelihood-incorrect-value + patterns: + - pattern-inside: | + rules: + ... + - pattern-inside: | + metadata: + ... + category: security + ... + - pattern: | + likelihood: $VALUE + - pattern-not: | + likelihood: LOW + - pattern-not: | + likelihood: MEDIUM + - pattern-not: | + likelihood: HIGH + message: >- + Semgrep rule likelihood: $VALUE detected, but the value must be LOW, + MEDIUM, or HIGH. For more information visit: + https://semgrep.dev/docs/contributing/contributing-to-semgrep-rules-repository/ + languages: + - yaml + severity: WARNING + metadata: + references: + - https://semgrep.dev/docs/contributing/contributing-to-semgrep-rules-repository/ + category: correctness + technology: + - semgrep +- id: yaml.semgrep.metadata-likelihood.metadata-likelihood + patterns: + - pattern-inside: | + rules: + ... + - pattern-inside: | + metadata: + ... + category: security + ... + - pattern-not-inside: | + metadata: + ... + likelihood: $VALUE + message: >- + This Semgrep rule is missing a valid 'likelihood' field in the 'metadata'. + which should be either LOW, MEDIUM, or HIGH. For more information visit + https://semgrep.dev/docs/contributing/contributing-to-semgrep-rules-repository/ + languages: + - yaml + severity: WARNING + metadata: + references: + - https://semgrep.dev/docs/contributing/contributing-to-semgrep-rules-repository/ + category: correctness + technology: + - semgrep +- id: yaml.semgrep.metadata-owasp.metadata-owasp + message: >- + The `owasp` tag in Semgrep rule metadata should start with the format "A00:YYYY", + where A00 is the OWASP top ten number and YYYY is the OWASP top ten year. + severity: ERROR + languages: [json, yaml] + patterns: + - pattern-inside: "rules: ..." + - pattern-inside: "metadata: ..." + - pattern-either: + # A single line year is optional, e.g. `owasp: "A1: blah"` or `owasp: A01:2021 blah` + # If there's a year, need leading zero, e.g. `A01:2021 blah` rather than `A1:2021 blah`. + - patterns: + - pattern: 'owasp: "..."' + - pattern-not: 'owasp: "=~/^A(0?[1-9]|10):\s+.+$/"' + - pattern-not: 'owasp: "=~/^A(0[1-9]|10):([0-9]{4})?\s+.+$/"' + # A list, must have the year, e.g. `- A01:2021 blah` + - patterns: + - pattern-inside: "owasp: [...]" + - pattern: '"$ANYTHING"' + - pattern-not-regex: .*A(0[1-9]|10):[0-9]{4}\s+.* + - pattern-not-regex: "owasp:" + metadata: + category: best-practice + technology: + - semgrep +- id: yaml.semgrep.metadata-references.metadata-references + message: >- + The references in rule metadata should always be a list, even if there's only one. + severity: ERROR + languages: [json, yaml] + patterns: + - pattern-inside: | + rules: ... + - pattern-inside: | + metadata: ... + - pattern: | + references: ... + - pattern-not: | + references: [...] + metadata: + category: correctness + technology: + - semgrep +- id: yaml.semgrep.metadata-subcategory-incorrect-value.metadata-subcategory-incorrect-value + patterns: + - pattern-inside: | + rules: + ... + - pattern-inside: | + metadata: + ... + category: security + ... + - pattern: | + subcategory: + - $VALUE + - pattern-not: | + subcategory: + - vuln + - pattern-not: | + subcategory: + - audit + - pattern-not: | + subcategory: + - guardrail + message: >- + Semgrep rule likelihood: $VALUE detected, but the value must be vuln, + audit, or guardrail. For more information visit: + https://semgrep.dev/docs/contributing/contributing-to-semgrep-rules-repository/ + languages: + - yaml + severity: WARNING + metadata: + references: + - https://semgrep.dev/docs/contributing/contributing-to-semgrep-rules-repository/ + category: correctness + technology: + - semgrep +- id: yaml.semgrep.metadata-subcategory.metadata-subcategory + patterns: + - pattern-inside: | + rules: + ... + - pattern-inside: | + metadata: + ... + category: security + ... + - pattern-not-inside: | + metadata: + ... + subcategory: $VALUE + message: >- + This Semgrep rule is missing a valid 'subcategory' field in the 'metadata'. + which should be either audit, vuln, or guardrail. For more information visit + https://semgrep.dev/docs/contributing/contributing-to-semgrep-rules-repository/ + languages: + - yaml + severity: WARNING + metadata: + references: + - https://semgrep.dev/docs/contributing/contributing-to-semgrep-rules-repository/ + category: correctness + technology: + - semgrep +- id: yaml.semgrep.metadata-technology.metadata-technology + message: >- + This Semgrep rule is missing a 'technology' field in the 'metadata'. + Consider adding a list of technologies based on the rule's associated + library or framework, or another piece of relevant information. + severity: INFO + pattern-either: + # non join mode + - patterns: + - pattern-not-inside: | + - ... + mode: join + - pattern-inside: "rules: [..., $RULE, ...]" + - pattern: $RULE + - pattern: | + id: ... + ... + - pattern-not: | + id: ... + ... + metadata: + ... + technology: + - ... + # join mode + - patterns: + - pattern-inside: | + id: $OUTER_RULEID + mode: join + join: + rules: [ ..., $INNER_RULE, ...] + ... + ... + - pattern-not: | + id: $OUTER_RULEID + ... + metadata: + ... + technology: + - ... + languages: [yaml] + metadata: + category: best-practice + technology: + - semgrep + references: + - https://semgrep.dev/docs/contributing/contributing-to-semgrep-rules-repository/#technology +- id: yaml.semgrep.missing-language-field.missing-language-field + message: >- + Please include a 'languages' field for your rule $RULEID! + languages: [yaml] + pattern-either: + # non join mode + - patterns: + - pattern-inside: "rules: [..., $RULE, ...]" + - pattern: "id: $RULEID" + - pattern-not-inside: | + - ... + languages: ... + - pattern-not-inside: | + - ... + mode: join + # join mode + - patterns: + - pattern-inside: | + rules: [ ..., $OUTER_RULE, ...] + - pattern-inside: $OUTER_RULE + - pattern-inside: | + id: $OUTER_RULEID + mode: join + join: + rules: [ ..., $INNER_RULE, ...] + ... + ... + - pattern-inside: $INNER_RULE + - pattern-not-inside: | + - languages: ... + ... + - pattern: | + id: $RULEID + severity: WARNING + metadata: + references: + - https://semgrep.dev/docs/writing-rules/rule-syntax/#required + category: correctness + technology: + - semgrep +- id: yaml.semgrep.missing-message-field.missing-message-field + message: >- + This rule does not have a message. Semgrep requires that + rules have a message. Include a message to explain what the rule does. + Consider writing a message that explains why this is an issue and + how to fix it. + languages: [yaml] + patterns: + - pattern-inside: "rules: [..., $RULE, ...]" + - pattern: "id: $RULEID" + - pattern-not-inside: | + - ... + message: ... + - pattern-not-inside: | + - ... + mode: extract + severity: WARNING + metadata: + category: correctness + technology: + - semgrep + references: + - https://semgrep.dev/docs/writing-rules/rule-syntax/ +- id: yaml.semgrep.multi-line-message.multi-line-message + message: >- + This rule has a multi-line message field, which may display poorly + in a terminal. Consider ensuring it is on one line. For example, + use `message: >-`, not `message: |`. + languages: [yaml] + patterns: + - pattern-inside: "rules: [..., $RULE, ...]" + - pattern: | + message: "=~/[\\n\\r]/" + severity: WARNING + metadata: + category: correctness + technology: + - semgrep + references: + - https://github.com/returntocorp/semgrep-rules/issues/1431 +- id: yaml.semgrep.rule-missing-deconstructed-value.missing-deconstructed-value + message: >- + Looks like this value is deconstructing a const/var/let you need to use + all three `const {...} =` `var {...} =` and `let {...} =` to provide + accurate coverage consider adding the missing patterns in a + `pattern-inside` for better coverage. + languages: + - yaml + severity: WARNING + metadata: + references: + - https://semgrep.dev/docs/contributing/contributing-to-semgrep-rules-repository + category: correctness + technology: + - semgrep + patterns: + - pattern-either: + - patterns: + - pattern-inside: | + rules: ... + - pattern-not-inside: | + - pattern-either: + ... + - pattern: | + - pattern-inside: + $VALUE + - pattern-either: + - pattern-regex: const {.*}.*= + - pattern-regex: let {.*}.*= + - pattern-regex: var {.*}.*= + - patterns: + - patterns: + - pattern-inside: | + rules: ... + - pattern-inside: | + - pattern-either: + $VALUE + - focus-metavariable: + - $VALUE + - pattern-inside: | + - pattern-inside: + $A + - metavariable-regex: + metavariable: $A + regex: .*\s.*(var|const|let)\s{.*}\s= + - pattern-not: + patterns: + - pattern-inside: | + ... + - pattern-inside: + $Z + ... + - pattern-inside: + $B + ... + - pattern-inside: + $C + ... + - metavariable-regex: + metavariable: $Z + regex: .*\s.*(var|const|let).*{.*} + - metavariable-regex: + metavariable: $B + regex: .*\s.*(var|const|let).*{.*} + - metavariable-regex: + metavariable: $C + regex: .*\s.*(var|const|let).*{.*} +- id: yaml.semgrep.slow-pattern-general-function.slow-pattern-general-func + languages: + - yaml + message: >- + Using patterns like `function (...) {...}` is too general it will probably slow down the rule performance. + patterns: + - pattern-either: + - pattern-inside: | + pattern-inside: $X + - pattern-inside: | + pattern-not-inside: $X + - pattern-inside: | + pattern: $X + - pattern-inside: | + pattern-not: $X + - pattern-regex: function[^{]*{[\s\n]*\.\.\.[\s\n]*} + - pattern-either: + - pattern-inside: | + languages: [...,"javascript",...] + ... + - pattern-inside: | + languages: [...,"typescript",...] + ... + severity: WARNING + metadata: + category: performance + technology: + - semgrep +- id: yaml.semgrep.slow-pattern-general-property.slow-pattern-general-property + languages: + - yaml + message: >- + Using patterns like `$X.$Y` may be too general and may slow down the rule performance. + patterns: + - pattern-either: + - pattern-inside: | + pattern-inside: $X + - pattern-inside: | + pattern-not-inside: $X + - pattern-inside: | + pattern: $X + - pattern-inside: | + pattern-not: $X + - pattern-regex: \$[A-Z]*\.\$[A-Z]* + severity: WARNING + metadata: + category: performance + technology: + - semgrep +- id: yaml.semgrep.slow-pattern-single-metavariable.slow-pattern-single-metavariable + languages: + - yaml + message: >- + Using a single metavariable as a pattern drastically slows down the rule performance + because it will match every expression in a file. Instead, try to match something + specific such as a function name, or anchor on a statement that may occur above + or below the pattern. The more specific you can be, the faster the pattern will run. + patterns: + - pattern-either: + - pattern-inside: | + pattern-inside: $PATTERN + - pattern-inside: | + pattern-not-inside: $PATTERN + - pattern-inside: | + pattern: $PATTERN + - pattern-inside: | + pattern-not: $PATTERN + - metavariable-regex: + metavariable: $PATTERN + regex: \$[A-Z_]* + severity: WARNING + metadata: + category: performance + technology: + - semgrep +- id: yaml.semgrep.slow-pattern-top-ellipsis.slow-pattern-top-ellipsis + languages: + - yaml + message: >- + Using the ellipsis operator `...` at the top of the pattern drastically slows down the rule performance. + patterns: + - pattern-either: + - pattern-inside: | + pattern-inside: $X + - pattern-inside: | + pattern-not-inside: $X + - pattern-inside: | + pattern: $X + - pattern-inside: | + pattern-not: $X + - pattern-regex: \|\s*\n\s*\.\.\.\s*\n[^\n]*\n\s*\.\.\. + severity: WARNING + metadata: + category: performance + technology: + - semgrep +- id: yaml.semgrep.unnecessary-parent.unnecessary-parent-operator + message: Unnecessary parent operator. Remove one to fix. + languages: [yaml] + patterns: + - pattern-inside: "rules: [..., $RULE, ...]" + - pattern-either: + - patterns: + - pattern: | + pattern-either: + - $THING1 + - ... + - pattern-not: | + pattern-either: + - $THING1 + - $THING2 + - ... + - patterns: + - pattern: | + patterns: + - $THING1 + - ... + - pattern-not: | + patterns: + - $THING1 + - $THING2 + - ... + - pattern: | + pattern-either: + - ... + - pattern-either: + - ... + severity: WARNING + metadata: + category: best-practice + technology: + - semgrep +- id: yaml.semgrep.unsatisfiable.unsatisfiable-rule + message: >- + You can not use 'pattern' $A and 'pattern-not' $A together; this will always be empty. + severity: ERROR + languages: [yaml] + patterns: + - pattern-inside: "patterns: [...]" + - pattern-either: + - patterns: + - pattern-inside: | + - pattern: $A + ... + - pattern: | + - pattern-not: $A + - patterns: + - pattern-inside: | + - pattern-not: $A + ... + - pattern: | + - pattern: $A + metadata: + category: correctness + technology: + - semgrep + +- id: c_access_rule-RpcImpersonateClient-ImpersonateLoggedOnUser + languages: + - "c" + - "cpp" + - "cpp" + message: | + These functions may be used to either drop or change account privileges. If the calls + fail, the process will continue to run with the privileges assigned to it on start. Depending + on + the logic of the application, this may allow attackers to abuse the system due to privileges + never + being changed to a different access level. + + Always ensure return values of this function are checked to determine if the application should + continue to operate. + metadata: + shortDescription: "Ensure return values are checked when attempting to drop privileges" + cwe: "CWE-250" + owasp: + - "A5:2017-Broken Access Control" + - "A01:2021-Broken Access Control" + security-severity: "High" + category: "security" + pattern-either: + - pattern: "RpcImpersonateClient(...)" + - pattern: "ImpersonateLoggedOnUser(...)" + - pattern: "CoImpersonateClient(...)" + - pattern: "ImpersonateNamedPipeClient(...)" + - pattern: "ImpersonateDdeClientWindow(...)" + - pattern: "ImpersonateSecurityContext(...)" + - pattern: "SetThreadToken(...)" + severity: "ERROR" +- id: c_access_rule-umask + languages: + - "c" + - "cpp" + - "cpp" + message: | + The umask function call sets the process's file mode creation mask. umask values determine + what permissions a file should be created with and who can read or write to these files. + Ensure that umask is given most restrictive possible setting depending on the context, + usually 066 or 077, for more information please see: + https://en.wikipedia.org/wiki/Umask#Mask_effect. + metadata: + shortDescription: "Ensure restrictive umask values" + cwe: "CWE-732" + owasp: + - "A6:2017-Security Misconfiguration" + - "A05:2021-Security Misconfiguration" + security-severity: "High" + category: "security" + pattern: "umask(...)" + severity: "INFO" +- id: c_buffer_rule-MultiByteToWideChar + languages: + - "c" + - "cpp" + - "cpp" + message: | + The input buffer is the number of bytes in the string, but the size + of the output buffer is the number of characters. To avoid overflows, the + application must determine the correct buffer size which depends on the data type + the buffer receives. + + For more information see: + https://learn.microsoft.com/en-us/windows/win32/intl/security-considerations--international-features + metadata: + shortDescription: "Easily misused function may lead to buffer overflows" + cwe: "CWE-120" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "High" + category: "security" + pattern: "MultiByteToWideChar(...)" + severity: "INFO" +- id: c_buffer_rule-StrCat-StrCatA + languages: + - "c" + - "cpp" + - "cpp" + message: | + The `StrCat` family of functions do not guarantee the final string to be null terminated. + Consider using one of the following alternatives: `StringCbCat`, `StringCbCatEx`, + `StringCbCatN`, `StringCbCatNEx`, `StringCchCat`, `StringCchCatEx`, `StringCchCatN`, or + `StringCchCatNEx`. + + For more information please see: https://learn.microsoft.com/en-us/windows/win32/api/strsafe/ + metadata: + shortDescription: "Insecure string processing function" + cwe: "CWE-120" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "High" + category: "security" + pattern-either: + - pattern: "strcat(...)" + - pattern: "strcatA(...)" + - pattern: "StrcatW(...)" + - pattern: "lstrcatA(...)" + - pattern: "lstrcatW(...)" + - pattern: "strCatBuff(...)" + - pattern: "StrCatBuffA(...)" + - pattern: "StrCatBuffW(...)" + - pattern: "StrCatChainW(...)" + - pattern: "_tccat(...)" + - pattern: "_mbccat(...)" + - pattern: "_ftcscat(...)" + - pattern: "StrCatN(...)" + - pattern: "StrCatNA(...)" + - pattern: "StrCatNW(...)" + - pattern: "StrNCat(...)" + - pattern: "StrNCatA(...)" + - pattern: "StrNCatW(...)" + - pattern: "lstrncat(...)" + - pattern: "lstrcatnA(...)" + - pattern: "lstrcatnW(...)" + severity: "ERROR" +- id: c_buffer_rule-fscanf-sscanf + languages: + - "c" + - "cpp" + - "cpp" + message: | + Format specifiers can take optional field widths, which should be + used to limit how many characters are copied into the target buffer. + + Example: + ``` + const char str[20] = "AAAAAAAAAAAAAAAAAAA"; + char buf[11] = {0}; + sscanf(str, "%10s", &buf); // buf = AAAAAAAAAA\0 + ``` + metadata: + shortDescription: "sscanf() functions may allow format string based overflows" + cwe: "CWE-120" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "High" + category: "security" + pattern-either: + - pattern: "fscanf(...)" + - pattern: "sscanf(...)" + - pattern: "vsscanf(...)" + - pattern: "vfscanf(...)" + - pattern: "_ftscanf(...)" + - pattern: "fwscanf(...)" + - pattern: "vfwscanf(...)" + - pattern: "vswscanf(...)" + severity: "ERROR" +- id: c_buffer_rule-g-get-home-dir + languages: + - "c" + - "cpp" + - "cpp" + message: | + This function is synonymous with `getenv("HOME")` and should be treated + as untrusted input as it could be modified by an attacker. Possible risks + include: + + - The value being too large and causing buffer overflows + - Files under the attacker's control being used maliciously + - Files outside of an attacker's control becoming accessible, depending on + access privileges. + metadata: + shortDescription: "Reliance on untrusted inputs in a security decision" + cwe: "CWE-807" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "High" + category: "security" + pattern: "g_get_home_dir(...)" + severity: "WARNING" +- id: c_buffer_rule-g-get-tmp-dir + languages: + - "c" + - "cpp" + - "cpp" + message: | + This function is synonymous with `getenv("TMP")` and should be treated + as untrusted input as it could be modified by an attacker. Possible risks + include: + + - The value being too large and causing buffer overflows + - Files under the attacker's control being used maliciously + - Files outside of an attacker's control becoming accessible, depending on + access privileges. + metadata: + shortDescription: "Reliance on untrusted inputs in a security decision" + cwe: "CWE-807" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "High" + category: "security" + pattern: "g_get_tmp_dir(...)" + severity: "WARNING" +- id: c_buffer_rule-getenv-curl-getenv + languages: + - "c" + - "cpp" + - "cpp" + message: | + This function's return value should be treated as untrusted input as it could be + modified by an attacker. Possible risks include: + + - The value being too large and causing buffer overflows + - Files under the attacker's control being used maliciously + - Files outside of an attacker's control becoming accessible, depending on + access privileges. + metadata: + shortDescription: "Reliance on untrusted inputs in a security decision" + cwe: "CWE-807" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "High" + category: "security" + pattern-either: + - pattern: "getenv(...)" + - pattern: "curl_getenv(...)" + severity: "WARNING" +- id: c_buffer_rule-gets--getts + languages: + - "c" + - "cpp" + - "cpp" + message: | + The gets() function reads a line from stdin into the provided buffer + until either a terminating newline or EOF. This terminating newline or + EOF is replaced with a null byte `'\0'`. No check for buffer overruns are + performed so it is recommended to use `fgets()` instead. Do note + that some platforms will continue reading data after a `'\0'` is encountered. + + Usage of `fgets()` is not recommended for reading binary based files or inputs, + instead the `read` or `fread` functions should be used. + + For more information please see: https://linux.die.net/man/3/fgets + metadata: + shortDescription: "Use of deprecated function (gets)" + cwe: "CWE-120" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "High" + category: "security" + pattern-either: + - pattern: "gets(...)" + - pattern: "_getts(...)" + - pattern: "_getws(...)" + severity: "ERROR" +- id: c_buffer_rule-getwd + languages: + - "c" + - "cpp" + - "cpp" + message: | + `getwd` does not contain a parameter to limit how many characters can be copied into the + destination buffer. For portability and security reasons `getwd` has been deprecated in + favor of `getcwd`. + + For more information please see: https://linux.die.net/man/3/getcwd + metadata: + shortDescription: "Insufficient protection against buffer overflow (getwd)" + cwe: "CWE-120" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "High" + category: "security" + pattern: "getwd(...)" + severity: "WARNING" +- id: c_buffer_rule-lstrcat-wcscat + languages: + - "c" + - "cpp" + - "cpp" + message: | + The `strcat` family of functions are unable to limit how many bytes are copied + to the destination buffer. It is recommended to use more secure alternatives such as + `snprintf`. + + If developing for C Runtime Library (CRT), more secure versions of these functions should be + used, see: + https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/strcat-s-wcscat-s-mbscat-s?view=msvc-170 + metadata: + shortDescription: "Insecure functions unable to limit / check buffer sizes" + cwe: "CWE-120" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "High" + category: "security" + pattern-either: + - pattern: "lstrcat(...)" + - pattern: "wcscat(...)" + - pattern: "_tcscat(...)" + - pattern: "_mbscat(...)" + severity: "ERROR" +- id: c_buffer_rule-lstrcatn-wcsncat + languages: + - "c" + - "cpp" + - "cpp" + message: | + Consider using more secure alternatives such as `snprintf`, instead of the + `wcsncat` family of functions. + + If developing for C Runtime Library (CRT), more secure versions of these functions should be + used, see: + https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/strncat-strncat-l-wcsncat-wcsncat-l-mbsncat-mbsncat-l?view=msvc-170 + metadata: + shortDescription: "Easily misused string processing functions" + cwe: "CWE-120" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "High" + category: "security" + pattern-either: + - pattern: "lstrcatn(...)" + - pattern: "wcsncat(...)" + - pattern: "_tcsncat(...)" + - pattern: "_mbsnbcat(...)" + severity: "INFO" +- id: c_buffer_rule-lstrcpy-wcscpy + languages: + - "c" + - "cpp" + - "cpp" + message: | + The `lstrcpy` family of functions do not provide the ability to limit or check buffer + sizes before copying to a destination buffer. This can lead to buffer overflows. Consider + using more secure alternatives such as `strncpy_s`. + + If developing for C Runtime Library (CRT), more secure versions of these functions should be + used, see: + https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/strncpy-s-strncpy-s-l-wcsncpy-s-wcsncpy-s-l-mbsncpy-s-mbsncpy-s-l?view=msvc-170 + metadata: + shortDescription: "Insecure functions unable to limit / check buffer sizes" + cwe: "CWE-120" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "High" + category: "security" + pattern-either: + - pattern: "lstrcpy(...)" + - pattern: "wcscpy(...)" + - pattern: "_tcscpy(...)" + - pattern: "_mbscpy(...)" + severity: "ERROR" +- id: c_buffer_rule-lstrcpyn-wcsncpy + languages: + - "c" + - "cpp" + - "cpp" + message: | + The `lstrcpyn` family of functions do not always check for invalid pointers or check if there + is sufficient space prior to copying. The count argument limits the number of characters copied + but does validate if the count will fit within the size of the destination buffer, leading to + potential overflows. + + If developing for C Runtime Library (CRT), more secure versions of these functions should be + used, see: + https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/strncpy-s-strncpy-s-l-wcsncpy-s-wcsncpy-s-l-mbsncpy-s-mbsncpy-s-l?view=msvc-170 + metadata: + shortDescription: "Insecure functions do not always null terminate or check invalid + pointers" + cwe: "CWE-120" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "High" + category: "security" + pattern-either: + - pattern: "lstrcpyn(...)" + - pattern: "wcsncpy(...)" + - pattern: "_tcsncpy(...)" + - pattern: "_mbsnbcpy(...)" + severity: "INFO" +- id: c_buffer_rule-memcpy-CopyMemory + languages: + - "c" + - "cpp" + - "cpp" + message: | + The `memcpy` family of functions require the developer to validate that the destination buffer + is the same size or larger than the source buffer. Buffer overflows could be introduced if care + is not taken to validate buffer sizes. + + If developing for C Runtime Library (CRT), more secure versions of these functions should be + used, see: + https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/memcpy-s-wmemcpy-s?view=msvc-170 + metadata: + shortDescription: "Function does not check for buffer overflows when copying" + cwe: "CWE-120" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "High" + category: "security" + pattern-either: + - pattern: "memcpy(...)" + - pattern: "CopyMemory(...)" + - pattern: "bcopy(...)" + severity: "INFO" +- id: c_buffer_rule-realpath + languages: + - "c" + - "cpp" + - "cpp" + message: | + The `realpath` function should not be called with a destination buffer as it could + lead to overflowing if the path is greater than PATH_LEN. It is instead recommended + to call `realpath` with the destination buffer set to NULL and use the return value + as the resolved path. Be sure to free the returned pointer as realpath will allocate + the buffer internally using `malloc`. + + For more information see: https://linux.die.net/man/3/realpath + + Example: + + ``` + char const *symlink_path = "/tmp/symlink"; + char *resolved_path = NULL; + + resolved_path = realpath(symlink_path, NULL); + if (errno == 0) { + // ... use resolved_path... + free(resolved_path); + } + ``` + metadata: + shortDescription: "Function does not ensure destination buffer length is sufficient + before copying" + cwe: "CWE-120" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "High" + category: "security" + pattern: "realpath(...)" + severity: "WARNING" +- id: c_buffer_rule-scanf-vscanf + languages: + - "c" + - "cpp" + - "cpp" + message: | + Format specifiers can take optional field widths, which should be + used to limit how many characters are copied into the target buffer. + + For more information please see: https://linux.die.net/man/3/scanf + + Example: + ``` + char buf[11] = {0}; + scanf("%10s", &buf); // buf = AAAAAAAAAA\0 + ``` + + If developing for C Runtime Library (CRT), more secure versions of these functions should be + used, see: + https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/scanf-s-scanf-s-l-wscanf-s-wscanf-s-l?view=msvc-170 + metadata: + shortDescription: "scanf() functions may allow format string based overflows" + cwe: "CWE-120" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "High" + category: "security" + pattern-either: + - patterns: + - pattern: "scanf($FMT, ...)" + - pattern-not: "scanf(\"...\", ...)" + - patterns: + - pattern: "vscanf($FMT, ...)" + - pattern-not: "vscanf(\"...\", ...)" + - patterns: + - pattern: "wscanf($FMT, ...)" + - pattern-not: "wscanf(\"...\", ...)" + - patterns: + - pattern: "_tscanf($FMT, ...)" + - pattern-not: "_tscanf(_T(\"...\"), ...)" + - patterns: + - pattern: "vwscanf(FMT, ...)" + - pattern-not: "vwscanf(\"...\", ...)" + severity: "ERROR" +- id: c_buffer_rule-sprintf-vsprintf + languages: + - "c" + - "cpp" + - "cpp" + message: | + Use sprintf_s, snprintf, or vsnprintf instead. The `sprintf` family of functions do not allow + callers to set limits on how many bytes the destination buffer can hold. Consider using more + secure alternatives such as `snprintf`. + + For more information please see: https://linux.die.net/man/3/snprintf + + If developing for C Runtime Library (CRT), more secure versions of these functions should be + used, see: + https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/sprintf-s-sprintf-s-l-swprintf-s-swprintf-s-l?view=msvc-170 + metadata: + shortDescription: "Insecure function unable to limit / check buffer sizes" + cwe: "CWE-120" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "High" + category: "security" + pattern-either: + - pattern: "sprintf(...)" + - pattern: "vsprintf(...)" + - pattern: "swprintf(...)" + - pattern: "vswprintf(...)" + - pattern: "_stprintf(...)" + - pattern: "_vstprintf(...)" + severity: "ERROR" +- id: c_buffer_rule-strcat + languages: + - "c" + - "cpp" + - "cpp" + message: | + The `strcat` family of functions are unable to limit how many bytes are copied + to the destination buffer. It is recommended to use more secure alternatives such as + `snprintf`. + + For more information please see: https://linux.die.net/man/3/snprintf + + If developing for C Runtime Library (CRT), more secure versions of these functions should be + used, see: + https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/strcat-s-wcscat-s-mbscat-s?view=msvc-170 + metadata: + shortDescription: "Insecure string processing function" + cwe: "CWE-120" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "High" + category: "security" + pattern: "strcat(...)" + severity: "ERROR" +- id: c_buffer_rule-strccpy-strcadd + languages: + - "c" + - "cpp" + - "cpp" + message: | + The `strccpy` and `strcadd` functions do not allow the caller to check that the destination + size + of the buffer will fit the input buffer prior to copying. + + For more information please see: + https://docs.oracle.com/cd/E18752_01/html/816-5172/streadd-3gen.html + metadata: + shortDescription: "Insecure string processing functions" + cwe: "CWE-120" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "High" + category: "security" + pattern-either: + - pattern: "strccpy(...)" + - pattern: "strcadd(...)" + severity: "INFO" +- id: c_buffer_rule-strcpy + languages: + - "c" + - "cpp" + - "cpp" + message: | + The `strcpy` family of functions do not provide the ability to limit or check buffer + sizes before copying to a destination buffer. This can lead to buffer overflows. Consider + using more secure alternatives such as `strncpy` and provide the correct limit to the + destination buffer and ensure the string is null terminated. + + For more information please see: https://linux.die.net/man/3/strncpy + + If developing for C Runtime Library (CRT), more secure versions of these functions should be + used, see: + https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/strncpy-s-strncpy-s-l-wcsncpy-s-wcsncpy-s-l-mbsncpy-s-mbsncpy-s-l?view=msvc-170 + metadata: + shortDescription: "Insecure string processing function (strcpy)" + cwe: "CWE-120" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "High" + category: "security" + pattern: "strcpy(...)" + severity: "ERROR" +- id: c_buffer_rule-strcpyA-strcpyW + languages: + - "c" + - "cpp" + - "cpp" + message: | + The `StrCpy` family of functions do not guarantee the final string to be null terminated. + Consider + using one of the following alternatives `StringCbCopy`, `StringCbCopyEx`, `StringCbCopyN`, + `StringCbCopyNEx`, `StringCchCopy`, `StringCchCopyEx`, `StringCchCopyN`, or `StringCchCopyNEx`. + + If developing for C Runtime Library (CRT), more secure versions of these functions should be + used, see: + https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/strncpy-s-strncpy-s-l-wcsncpy-s-wcsncpy-s-l-mbsncpy-s-mbsncpy-s-l?view=msvc-170 + metadata: + shortDescription: "Insecure string processing function" + cwe: "CWE-120" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "High" + category: "security" + pattern-either: + - pattern: "strcpyA(...)" + - pattern: "strcpyW(...)" + - pattern: "StrCpy(...)" + - pattern: "StrCpyA(...)" + - pattern: "lstrcpyA(...)" + - pattern: "lstrcpyW(...)" + - pattern: "_tccpy(...)" + - pattern: "_mbccpy(...)" + - pattern: "_ftcscpy(...)" + - pattern: "_mbsncpy(...)" + - pattern: "StrCpyN(...)" + - pattern: "StrCpyNA(...)" + - pattern: "StrCpyNW(...)" + - pattern: "StrNCpy(...)" + - pattern: "strcpynA(...)" + - pattern: "StrNCpyA(...)" + - pattern: "StrNCpyW(...)" + - pattern: "lstrcpynA(...)" + - pattern: "lstrcpynW(...)" + severity: "ERROR" +- id: c_buffer_rule-streadd-strecpy + languages: + - "c" + - "cpp" + - "cpp" + message: | + The `strecpy` and `streadd` functions require that the destination buffer size be at least + four + times the size of the source due to each character potentially becoming a `\` and 3 digits. + + For more information please see: + https://docs.oracle.com/cd/E18752_01/html/816-5172/streadd-3gen.html + metadata: + shortDescription: "Insecure string processing functions" + cwe: "CWE-120" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "High" + category: "security" + pattern-either: + - pattern: "streadd(...)" + - pattern: "strecpy(...)" + severity: "ERROR" +- id: c_buffer_rule-strlen-wcslen + languages: + - "c" + - "cpp" + - "cpp" + message: | + The `strlen` family of functions does not handle strings that are not null + terminated. This can lead to buffer over reads and cause the application to + crash by accessing unintended memory locations. It is recommended that `strnlen` + be used instead as a `maxlen` value can be provided. + + For more information please see: https://linux.die.net/man/3/strnlen + + If developing for C Runtime Library (CRT), more secure versions of these functions should be + used, see: + https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/strnlen-strnlen-s?view=msvc-170 + metadata: + shortDescription: "Function does not handle null terminated strings properly" + cwe: "CWE-126" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "High" + category: "security" + pattern-either: + - pattern: "strlen(...)" + - pattern: "wcslen(...)" + - pattern: "_tcslen(...)" + - pattern: "_mbslen(...)" + severity: "INFO" +- id: c_buffer_rule-strncat + languages: + - "c" + - "cpp" + - "cpp" + message: | + The `strncat` family of functions are easy to use incorrectly when calculating destination + buffer + sizes. It is recommended to use more secure alternatives such as `snprintf`. + + For more information please see: https://linux.die.net/man/3/snprintf + + If developing for C Runtime Library (CRT), more secure versions of these functions should be + used, see: + https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/strncat-s-strncat-s-l-wcsncat-s-wcsncat-s-l-mbsncat-s-mbsncat-s-l?view=msvc-170 + metadata: + shortDescription: "Function does not handle null terminated strings or invalid + pointers properly" + cwe: "CWE-120" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "High" + category: "security" + pattern: "strncat(...)" + severity: "INFO" +- id: c_buffer_rule-strncpy + languages: + - "c" + - "cpp" + - "cpp" + message: | + The `strncpy` family of functions do not properly handle strings that are not null terminated. + It is recommended to use more secure alternatives such as `snprintf`. + + For more information please see: https://linux.die.net/man/3/snprintf + + If developing for C Runtime Library (CRT), more secure versions of these functions should be + used, see: + https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/strncpy-s-strncpy-s-l-wcsncpy-s-wcsncpy-s-l-mbsncpy-s-mbsncpy-s-l?view=msvc-170 + metadata: + shortDescription: "Function does not handle null terminated strings or invalid + pointers properly" + cwe: "CWE-120" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "High" + category: "security" + pattern: "strncpy(...)" + severity: "INFO" +- id: c_buffer_rule-strtrns + languages: + - "c" + - "cpp" + - "cpp" + message: | + This function is easy to misuse by not accounting for the space necessary when transforming + strings. Ensure that the destination buffer is large enough to fit the transformed output. + + For more information please see: + https://docs.oracle.com/cd/E36784_01/html/E36877/strtrns-3gen.html + metadata: + shortDescription: "Insecure string processing function" + cwe: "CWE-120" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "High" + category: "security" + pattern: "strtrns(...)" + severity: "WARNING" +- id: c_crypto_rule-EVP-des-ecb-EVP-des-cbc + languages: + - "c" + - "cpp" + - "cpp" + message: | + The DES algorithm has not been recommended for over 15 years and was withdrawn from NIST (FIPS + 46-3) in 2005. + + Consider using libsodium's `crypto_secretbox_easy` authenticated encryption functions instead. + + For more information please see: + https://libsodium.gitbook.io/doc/secret-key_cryptography/secretbox. + + If you must be FIPS compliant, consider using OpenSSLs AES or 3DES ciphers. + metadata: + shortDescription: "Insecure encryption algorithm (DES)" + cwe: "CWE-327" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + security-severity: "Medium" + category: "security" + pattern-either: + - pattern: "EVP_des_ecb(...)" + - pattern: "EVP_des_cbc(...)" + - pattern: "EVP_des_cfb(...)" + - pattern: "EVP_des_ofb(...)" + - pattern: "EVP_desx_cbc(...)" + severity: "ERROR" +- id: c_crypto_rule-EVP-rc4-40-EVP-rc2-40-cbc + languages: + - "c" + - "cpp" + - "cpp" + message: | + The RC4 algorithm is vulnerable to many attacks and should no longer be used for encrypting + data streams. + + Consider using libsodium's `crypto_secretstream_xchacha20poly1305` stream cipher encryption + functions instead. For more information please see: + https://libsodium.gitbook.io/doc/secret-key_cryptography/secretstream + + If you must be FIPS compliant, consider using OpenSSLs AES or 3DES ciphers. + metadata: + shortDescription: "Insecure stream cipher (RC4)" + cwe: "CWE-327" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + security-severity: "Medium" + category: "security" + pattern-either: + - pattern: "EVP_rc4_40(...)" + - pattern: "EVP_rc2_40_cbc(...)" + - pattern: "EVP_rc2_64_cbc(...)" + severity: "ERROR" +- id: c_crypto_rule-crypt-crypt-r + languages: + - "c" + - "cpp" + - "cpp" + message: | + The crypt functions are not recommended due to the significantly small + key space. Modern hardware can crack crypt produced passwords relatively quickly. + + Consider using the Argon2id password hashing algorithm provided by libsodium. + For more information please see: https://libsodium.gitbook.io/doc/password_hashing. + metadata: + shortDescription: "Insecure hashing algorithm" + cwe: "CWE-327" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + security-severity: "Medium" + category: "security" + pattern-either: + - pattern: "crypt(...)" + - pattern: "crypt_r(...)" + severity: "ERROR" +- id: c_format_rule-fprintf-vfprintf + languages: + - "c" + - "cpp" + - "cpp" + message: | + Format string vulnerabilities allow an attacker to read or in some cases, + potentially write data to + and from locations in the processes' memory. To prevent against format + string attacks, do not allow + users or un-validated input to provide the format specification. + Consider using a constant for the format specification, or only allow specific + characters to be provided to the format argument for the `fprintf` family of functions. + + For more information please see: https://linux.die.net/man/3/fprintf + + For more information on format string attacks please see OWASP's attack + guide: https://owasp.org/www-community/attacks/Format_string_attack + metadata: + shortDescription: "Potential format string vulnerability" + cwe: "CWE-134" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "High" + category: "security" + pattern-either: + - patterns: + - pattern: "fprintf($FD, $FMT, ...)" + - pattern-not: "fprintf($FD, \"...\", ...)" + - patterns: + - pattern: "vfprintf($FMT, $ARGS, ...)" + - pattern-not: "vfprintf(\"...\", $ARGS, ...)" + - patterns: + - pattern: "_ftprintf($FD, $FMT, ...)" + - pattern-not: "_ftprintf($FD, \"...\", ...)" + - patterns: + - pattern: "fwprintf($FD, $FMT, ...)" + - pattern-not: "fwprintf($FD, \"...\", ...)" + - patterns: + - pattern: "fvwprintf($FD, $FMT, ...)" + - pattern-not: "fvwprintf($FD, \"...\", ...)" + severity: "ERROR" +- id: c_format_rule-printf-vprintf + languages: + - "c" + - "cpp" + - "cpp" + message: | + Format string vulnerabilities allow an attacker to read or in some cases, potentially write + data to + and from locations in the processes' memory. To prevent against format string attacks, do not + allow + users or un-validated input to provide the format specification. + Consider using a constant for the format specification, or only allow specific + characters to be provided to the format argument for the `printf` family of functions. + + For more information please see: https://linux.die.net/man/3/fprintf + + For more information on format string attacks please see OWASP's attack guide: + https://owasp.org/www-community/attacks/Format_string_attack + metadata: + shortDescription: "Potential format string vulnerability" + cwe: "CWE-134" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "High" + category: "security" + pattern-either: + - patterns: + - pattern: "printf(...)" + - pattern-not: "printf(\"...\",...)" + - patterns: + - pattern: "vprintf($FMT, ...)" + - pattern-not: "vprintf(\"...\", ...)" + - patterns: + - pattern: "vwprintf($FMT, ...)" + - pattern-not: "vwprintf(\"...\", ...)" + - patterns: + - pattern: "vfwprintf($FILE, $FMT, ...)" + - pattern-not: "vfwprintf($FILE, \"...\", ...)" + - patterns: + - pattern: "_vtprintf($FILE, $FMT, ...)" + - pattern-not: "_vtprintf($FILE, \"...\", ...)" + - patterns: + - pattern: "wprintf($FMT, ...)" + - pattern-not: "wprintf(\"...\", ...)" + severity: "ERROR" +- id: c_format_rule-snprintf-vsnprintf + languages: + - "c" + - "cpp" + - "cpp" + message: | + Format string vulnerabilities allow an attacker to read or in some cases, potentially write + data to + and from locations in the processes' memory. To prevent against format string attacks, do not + allow + users or un-validated input to provide the format specification. + Consider using a constant for the format specification, or strip all format + specifiers from the input prior to calling the `snprintf` family of functions. + + Note that some variations of this function do not always null terminate the strings. + + For more information on using snprintf please see: https://linux.die.net/man/3/snprintf + + For more information on format string attacks please see OWASP's attack guide: + https://owasp.org/www-community/attacks/Format_string_attack + metadata: + shortDescription: "Potential format string vulnerability" + cwe: "CWE-134" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "High" + category: "security" + pattern-either: + - patterns: + - pattern: "snprintf($BUF,$SIZE,$FMT,...)" + - pattern-not: "snprintf($BUF,$SIZE,\"...\",...)" + - patterns: + - pattern: "vsnprintf($BUF,$SIZE,$FMT)" + - pattern-not: "vsnprintf($BUF,$SIZE,\"...\",...)" + - patterns: + - pattern: "_snprintf($BUF,$SIZE,$FMT,...)" + - pattern-not: "_snprintf($BUF,$SIZE,$FMT,\"...\",...)" + - patterns: + - pattern: "_sntprintf($VAR,$FMT,...)" + - pattern-not: "sntprintf($VAR,\"...\",...)" + - patterns: + - pattern: "_vsntprintf($VAR,$FMT,...)" + - pattern-not: "_vsntprintf($VAR,\"...\",...)" + severity: "ERROR" +- id: c_format_rule-syslog + languages: + - "c" + - "cpp" + - "cpp" + message: | + Format string vulnerabilities allow an attacker to read or in some cases, potentially write + data to + and from locations in the processes' memory. To prevent against format string attacks, do not + allow + users or un-validated input to provide the format specification. + Consider using a constant for the format specification, or strip all format + specifiers from the input prior to calling the `syslog` function. + + For more information please see: https://capec.mitre.org/data/definitions/67.html + metadata: + shortDescription: "Potential format string vulnerability in syslog call" + cwe: "CWE-134" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "High" + category: "security" + pattern-either: + - patterns: + - pattern: "syslog($FUNC,...)" + - pattern-not: "syslog($FUNC,\"...\",...)" + severity: "ERROR" +- id: c_free_rule-memalign + languages: + - "c" + - "cpp" + - "cpp" + message: | + The `memalign` function may not check that the alignment argument is correct. Calling + free (on non Linux-based systems) may fail and in certain circumstances this failure + may be exploitable. This function has been deprecated in favor of `posix_memalign`. + + For more information please see: https://linux.die.net/man/3/memalign + metadata: + shortDescription: "Use of deprecated function (memalign)" + cwe: "CWE-676" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "High" + category: "security" + pattern-either: + - pattern: "memalign(...)" + - pattern-regex: "(void)\\s\\*(\\s|)(memalign)\\;" + severity: "INFO" +- id: c_integer_rule-atoi-atol + languages: + - "c" + - "cpp" + - "cpp" + message: | + The `atoi` family of functions can potentially overflow or underflow integer values. Consider + using `stroul` instead. + + For more information please see: + https://wiki.sei.cmu.edu/confluence/display/c/ERR34-C.+Detect+errors+when+converting+a+string+to+a+number + metadata: + shortDescription: "Possible integer overflow or underflow" + cwe: "CWE-190" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "Medium" + category: "security" + pattern-either: + - pattern: "atoi(...)" + - pattern: "atol(...)" + - pattern: "_wtoi(...)" + - pattern: "_wtoi64(...)" + severity: "INFO" +- id: c_misc_rule-AddAccessAllowedAce + languages: + - "c" + - "cpp" + - "cpp" + message: | + Make sure that you set inheritance by hand if you wish it to inherit. + metadata: + cwe: "CWE-732" + owasp: + - "A5:2017-Broken Access Control" + - "A01:2021-Broken Access Control" + shortDescription: "This doesn't set the inheritance bits in the access control + entry (ACE) header (CWE-732)" + security-severity: "High" + category: "security" + pattern: "AddAccessAllowedAce(...)" + severity: "WARNING" +- id: c_misc_rule-LoadLibrary + languages: + - "c" + - "cpp" + - "cpp" + message: | + The `LoadLibrary` function is used to load DLLs dynamically. Depending on the filepath + parameter, + the OS version, and the modes set for the process prior to calling LoadLibrary, DLL hijacking + may + be possible. Attackers can exploit this by placing DLL files with the same name in directories + that + are searched before the legitimate DLL is. + + To assist in preventing against this class of vulnerability consider: + - Specifying a fully qualified path when using LoadLibraryEx. + - Use the `LOAD_LIBRARY_SEARCH` flags with LoadLibraryEx or with SetDefaultDllDirectories. + - If you use SetDefaultDllDirectories, be sure to use the AddDllDirectory or SetDllDirectory + functions to modify the list of directories. + - Only use `SearchPath` if the `SetSearchPathMode` function is called with + `BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE`. (Note: this only moves the current directory to + the end of the SearchPath search list.) + + For more information see the security remarks section of the MSDN documentation: + https://learn.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibrarya#security-remarks + + For general information securely loading dynamic link libraries, see the MSDN documentation: + https://learn.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-security + metadata: + shortDescription: "Uncontrolled search path element" + cwe: "CWE-427" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "High" + category: "security" + pattern: "LoadLibrary(...)" + severity: "WARNING" +- id: c_misc_rule-LoadLibraryEx + languages: + - "c" + - "cpp" + - "cpp" + message: | + The `LoadLibraryEx` function is used to load DLLs dynamically. Depending on the filepath + parameter, + the OS version, and the modes set for the process prior to calling LoadLibrary, DLL hijacking + may + be possible. Attackers can exploit this by placing DLL files with the same name in directories + that + are searched before the legitimate DLL is. + + To assist in preventing against this class of vulnerability consider: + - Specifying a fully qualified path when using LoadLibraryEx. + - Use the `LOAD_LIBRARY_SEARCH` flags with LoadLibraryEx or with SetDefaultDllDirectories. + - If you use SetDefaultDllDirectories, be sure to use the AddDllDirectory or SetDllDirectory + functions to modify the list of directories. + - Only use `SearchPath` if the `SetSearchPathMode` function is called with + `BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE`. (Note: this only moves the current directory to + the end of the SearchPath search list.) + + For more information see the security remarks section of the MSDN documentation: + https://learn.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibrarya#security-remarks + + For general information securely loading dynamic link libraries, see the MSDN documentation: + https://learn.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-security + metadata: + shortDescription: "Uncontrolled search path element" + cwe: "CWE-427" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "High" + category: "security" + pattern: "LoadLibraryEx(...)" + severity: "WARNING" +- id: c_misc_rule-SetSecurityDescriptorDacl + languages: + - "c" + - "cpp" + - "cpp" + message: | + When `SetSecurityDescriptorDacl` is called with a null `pDacl` parameter and the + `bDaclPresent` flag is `TRUE`, all access to the object is allowed. An attacker + could set the object to Deny all, which would include even the Administrator user(s). + + Either call `SetSecurityDescriptorDacl` with bDaclPresent as `FALSE`, or supply a valid + non-null `pDacl` parameter value. + + For more information please see: + https://learn.microsoft.com/en-us/windows/win32/api/securitybaseapi/nf-securitybaseapi-setsecuritydescriptordacl#remarks + metadata: + shortDescription: "Null ACL when calling SetSecurityDescriptorDacl may allow all + access to objects" + cwe: "CWE-732" + owasp: + - "A5:2017-Broken Access Control" + - "A01:2021-Broken Access Control" + security-severity: "Medium" + category: "security" + pattern: "SetSecurityDescriptorDacl(...)" + severity: "ERROR" +- id: c_misc_rule-cuserid + languages: + - "c" + - "cpp" + - "cpp" + message: | + `cuserid()` is poorly defined (e.g., some systems use the effective + UID, like Linux, while others like System V use the real UID). Therefore, you can't trust + what it does. The cuserid function was included in the 1988 version of POSIX, but removed + from the 1990 version. Also, if passed a non-null parameter, there's a risk of a buffer + overflow if the passed-in buffer is not at least `L_cuserid` characters long. + + Use `getpwuid(geteuid())` and extract the desired information instead. + + For more information please see: https://linux.die.net/man/3/getpwuid + metadata: + shortDescription: "Usage of deprecated function (cuserid)" + cwe: "CWE-120" + owasp: + - "A9:2017-Using Components with Known Vulnerabilities" + - "A06:2021-Vulnerable and Outdated Components" + security-severity: "Low" + category: "security" + pattern: "cuserid(...)" + severity: "ERROR" +- id: c_misc_rule-fopen-open + languages: + - "c" + - "cpp" + - "cpp" + message: | + Usage of the `open` family of functions may hint at a potential Time Of Check Time Of Use + (TOCTOU) + vulnerability. An attacker may be able to modify the file being specified by the `open` + function prior to the `open` function being called. + + Prior to calling `open`, use `lstat` to open the file and confirm the attributes + are correct. Then use `open` to get a file descriptor to this file. Call `fstat` on the + `open` file descriptor to confirm that `st_dev` and `st_ino` are equal between the two. + If they are, it is safe to read and operate on the file's contents. + + For more information please see: + https://wiki.sei.cmu.edu/confluence/display/c/FIO45-C.+Avoid+TOCTOU+race+conditions+while+accessing+files + metadata: + shortDescription: "Potential time of check time of use vulnerability (open/fopen)" + cwe: "CWE-362" + owasp: + - "A5:2017-Broken Access Control" + - "A01:2021-Broken Access Control" + security-severity: "Medium" + category: "security" + pattern-either: + - pattern: "fopen(...)" + - pattern: "open(...)" + severity: "INFO" +- id: c_misc_rule-getlogin + languages: + - "c" + - "cpp" + - "cpp" + message: | + The `getlogin` function suffers from many bugs or unknown behaviors depending on the + system. Often, it gives only the first 8 characters of the login name. The user + currently logged in on the controlling TTY of our program does not necessarily mean + it is the user who started the process. + + Use getpwuid(geteuid()) and extract the desired information instead. + + For more information please see: https://linux.die.net/man/3/getpwuid + metadata: + shortDescription: "Usage of deprecated function (getlogin)" + cwe: "CWE-807" + owasp: + - "A9:2017-Using Components with Known Vulnerabilities" + - "A06:2021-Vulnerable and Outdated Components" + security-severity: "Low" + category: "security" + pattern: "getlogin(...)" + severity: "ERROR" +- id: c_misc_rule-getpass + languages: + - "c" + - "cpp" + - "cpp" + message: | + This function is obsolete and not portable. It was in SUSv2 but removed by POSIX.2. What + it does exactly varies considerably between systems, particularly in where its prompt is + displayed and where it gets its data. Some systems will write to stderr instead of stdout. + Some will read from stdin if it can not be read from /dev/tty. In some systems the + buffer is static and limited to 127 characters, meaning the full password may not be returned + properly. + + If you want to read input without terminal echoing enabled, see the description of the ECHO + flag + in the termios manual pager. If you ever read passwords from a terminal, be sure to zero the + password as soon as possible, to avoid leaving the cleartext password visible in the + process' address space. + metadata: + shortDescription: "Use of obsolete function" + cwe: "CWE-477" + owasp: + - "A9:2017-Using Components with Known Vulnerabilities" + - "A06:2021-Vulnerable and Outdated Components" + security-severity: "Low" + category: "security" + pattern: "getpass(...)" + severity: "ERROR" +- id: c_obsolete_rule-gsignal-ssignal + languages: + - "c" + - "cpp" + - "cpp" + message: | + The `gsignal` and `ssignal` functions are obsolete and no longer recommended. Consider + using the `raise` or `sigaction` functions instead for process signaling. + + For more information please see: https://linux.die.net/man/3/sigaction + metadata: + shortDescription: "Deprecated function calls (ssignal/gsignal)" + cwe: "CWE-676" + owasp: + - "A9:2017-Using Components with Known Vulnerabilities" + - "A06:2021-Vulnerable and Outdated Components" + security-severity: "Info" + category: "security" + pattern-either: + - pattern: "gsignal(...)" + - pattern: "ssignal(...)" + severity: "INFO" +- id: c_obsolete_rule-ulimit + languages: + - "c" + - "cpp" + - "cpp" + message: | + The ulimit function is obsolete and no longer recommended. Use `getrlimit(2)`, + `setrlimit`, or `sysconf` instead. + + For more information please see: https://linux.die.net/man/3/setrlimit + metadata: + shortDescription: "Usage of deprecated function (ulimit)" + cwe: "CWE-676" + owasp: + - "A9:2017-Using Components with Known Vulnerabilities" + - "A06:2021-Vulnerable and Outdated Components" + security-severity: "Info" + category: "security" + pattern: "ulimit(...)" + severity: "INFO" +- id: c_obsolete_rule-usleep + languages: + - "c" + - "cpp" + - "cpp" + message: | + The `usleep` function has been deprecated, use `nanosleep` or `setitimer` instead. + + For more information please see: https://linux.die.net/man/3/setitimer + metadata: + shortDescription: "Usage of deprecated function (usleep)" + cwe: "CWE-676" + owasp: + - "A9:2017-Using Components with Known Vulnerabilities" + - "A06:2021-Vulnerable and Outdated Components" + security-severity: "Info" + category: "security" + pattern: "usleep(...)" + severity: "INFO" +- id: c_race_rule-access + languages: + - "c" + - "cpp" + - "cpp" + message: | + Usage of the `access` function call hints at a potential Time Of Check Time Of Use (TOCTOU) + vulnerability. Using the `access` function to check if a file exists and is readable before + opening it, an attacker can create a race condition between the `access` call and + opening the file. The attacker could replace the file with a different one or modify its + content between the time the `access` function is called and the file is opened, thus + bypassing the permission check. + + Call `setuid` to drop privileges on the process prior to opening any files. Instead of using + `access`, use `lstat` prior to opening the file and confirm the attributes are correct. Then + use `open` to get a file descriptor to this file. Call `fstat` on the `open` file descriptor + to confirm that `st_dev` and `st_ino` are equal between the two. If they are, it is safe to + read and operate on the file's contents. + + For more information please see: + https://wiki.sei.cmu.edu/confluence/display/c/FIO45-C.+Avoid+TOCTOU+race+conditions+while+accessing+files + metadata: + shortDescription: "Potential time of check time of use vulnerability (access)" + cwe: "CWE-362" + owasp: + - "A5:2017-Broken Access Control" + - "A01:2021-Broken Access Control" + security-severity: "Medium" + category: "security" + pattern: "access(...)" + severity: "ERROR" +- id: c_race_rule-chmod + languages: + - "c" + - "cpp" + - "cpp" + message: | + Usage of the `chmod` function call hints at a potential Time Of Check Time Of Use (TOCTOU) + vulnerability. An attacker may be able to modify the file being specified by the `chmod` + function prior to the `chmod` function being called. Since `chmod` will resolve symbolic links, + an attacker may be able to exploit this fact to have files outside of their control modified. + + It is recommended that the `fchmod` function be used instead since this function takes + a file descriptor instead of a file. Ensure the opened file descriptor is pointing to + the correct file or directory prior to executing `fchmod` or any other file based operations. + + For more information please see: + https://wiki.sei.cmu.edu/confluence/display/c/FIO01-C.+Be+careful+using+functions+that+use+file+names+for+identification + metadata: + shortDescription: "Potential time of check time of use vulnerability (chmod)" + cwe: "CWE-362" + owasp: + - "A5:2017-Broken Access Control" + - "A01:2021-Broken Access Control" + security-severity: "Medium" + category: "security" + pattern: "chmod(...)" + severity: "ERROR" +- id: c_race_rule-chown + languages: + - "c" + - "cpp" + - "cpp" + message: | + Usage of the `chown` function call hints at a potential Time Of Check Time Of Use (TOCTOU) + vulnerability. An attacker may be able to modify the file being specified by the `chmod` + function prior to the `chown` function being called. Since `chown` will resolve symbolic links, + an attacker may be able to exploit this fact to have files outside of their control modified. + + It is recommended that the `fchown` or the `lchown` functions be used instead. The `fchown` + function takes a file descriptor instead of a file. The `lchown` function does not follow + symbolic links. Ensure the opened file descriptor is pointing to the correct file or + directory prior to executing `fchown` or any other file based operations. + + For more information please see: + https://wiki.sei.cmu.edu/confluence/display/c/FIO01-C.+Be+careful+using+functions+that+use+file+names+for+identification + metadata: + shortDescription: "Potential time of check time of use vulnerability (chown)" + cwe: "CWE-362" + owasp: + - "A5:2017-Broken Access Control" + - "A01:2021-Broken Access Control" + security-severity: "Medium" + category: "security" + pattern: "chown(...)" + severity: "ERROR" +- id: c_race_rule-readlink + languages: + - "c" + - "cpp" + - "cpp" + message: | + Usage of the `readlink` function call hints at a potential Time Of Check Time Of Use (TOCTOU) + vulnerability. An attacker may be able to modify the file being specified by the `readlink` + function prior to the `readlink` function being called. Additionally, care must be taken + that the buffer provided is large enough to hold the contents of the file. + + Instead of using `readlink`, use `lstat` prior to opening the file and confirm the attributes + are correct. Then use `open` to get a file descriptor to this file. Call `fstat` on the + `open` file descriptor to confirm that `st_dev` and `st_ino` are equal between the two. + If they are, it is safe to read and operate on the file's contents. + + For more information please see: + https://wiki.sei.cmu.edu/confluence/display/c/FIO45-C.+Avoid+TOCTOU+race+conditions+while+accessing+files + metadata: + shortDescription: "Time-of-check time-of-use (TOCTOU) race condition" + cwe: "CWE-367" + owasp: + - "A5:2017-Broken Access Control" + - "A01:2021-Broken Access Control" + security-severity: "Medium" + category: "security" + pattern: "readlink(...)" + severity: "ERROR" +- id: c_race_rule-vfork + languages: + - "c" + - "cpp" + - "cpp" + message: | + The `vfork` function is suffers from portability issues and is not recommended. In + some Linux systems `vfork` is vulnerable to a race condition while the child process + is running as the user's UID but hasn't executed `execve`. The user may be able to send + signals to this process, which in `vfork` would not be sent to the parent process. As + a result a user may be able to cause a denial of service against the privileged process. + + Use `fork` instead and be aware of other potential Time Of Check Time Of Use (TOCTOU) + vulnerabilities. + + For more information please see: + https://wiki.sei.cmu.edu/confluence/display/c/POS38-C.+Beware+of+race+conditions+when+using+fork+and+file+descriptors + metadata: + shortDescription: "Potential time of check time of use vulnerability (vfork)" + cwe: "CWE-362" + owasp: + - "A5:2017-Broken Access Control" + - "A01:2021-Broken Access Control" + security-severity: "Medium" + category: "security" + pattern: "vfork(...)" + severity: "INFO" +- id: c_random_rule-drand48-erand48 + languages: + - "c" + - "cpp" + - "cpp" + message: | + The detected function is not sufficient at generating security-related random numbers, + such as those used in key and nonce creation. Consider using the libsodium library's + `randombytes_random` function instead. More information on libsodium's random number + generators can be found here: https://libsodium.gitbook.io/doc/generating_random_data. + + If FIPS validation is required, consider using OpenSSLs `RAND_bytes` family of functions after + enabling the `FIPS_mode_set`. + + For more information on OpenSSL random numbers please see: + https://wiki.openssl.org/index.php/Random_Numbers + metadata: + shortDescription: "Usage of insufficient random number generators" + cwe: "CWE-327" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + security-severity: "Medium" + category: "security" + pattern-either: + - pattern: "drand48(...)" + - pattern: "erand48(...)" + - pattern: "jrand48(...)" + - pattern: "lcong48(...)" + - pattern: "lrand48(...)" + - pattern: "mrand48(...)" + - pattern: "nrand48(...)" + - pattern: "random(...)" + - pattern: "seed48(...)" + - pattern: "setstate(...)" + - pattern: "srand(...)" + - pattern: "strfry(...)" + - pattern: "srandom(...)" + - pattern: "g_rand_boolean(...)" + - pattern: "g_rand_int(...)" + - pattern: "g_rand_int_range(...)" + - pattern: "g_rand_double(...)" + - pattern: "g_rand_double_range(...)" + - pattern: "g_random_boolean(...)" + - pattern: "g_random_int(...)" + - pattern: "g_random_int_range(...)" + - pattern: "g_random_double(...)" + - pattern: "g_random_double_range(...)" + - pattern-regex: "(long|short|double|int|float|void)\\s(\\*|)(\\s|)(seed48|lcong48)(\\(.*\\))\\;" + severity: "WARNING" +- id: c_shell_rule-CreateProcess + languages: + - "c" + - "cpp" + - "cpp" + message: | + Due to how `CreateProcess` parses spaces, an attacker may be able to exploit this function + by creating a binary with the same name that is loaded first, depending on the search path + order. + + Ensure that quotation marks around the executable path are used, such as: + ``` + CreateProcessA(NULL, "\"C:\\Program Files\\MyApp.exe\"", ...) + ``` + For more information, please see MSDNs documentation at: + https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessa#security-remarks + metadata: + shortDescription: "Possible executable path hijacking (CreateProcess)" + cwe: "CWE-78" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "High" + category: "security" + pattern: "CreateProcess(...)" + severity: "WARNING" +- id: c_shell_rule-CreateProcessAsUser-CreateProcessWithLogon + languages: + - "c" + - "cpp" + - "cpp" + message: | + Due to how `CreateProcess` parses spaces, an attacker may be able to exploit this function + by creating a binary with the same name that is loaded first, depending on the search path + order. + + Ensure that quotation marks around the executable path are used, such as: + ``` + CreateProcessAsUser(hToken, NULL, "\"C:\\Program Files\\MyApp.exe\"", ...) + ``` + For more information, please see MSDNs documentation at: + https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessasusera#security-remarks + metadata: + shortDescription: "Possible executable path hijacking (CreateProcessAsUser/CreateProcessWithLogon)" + cwe: "CWE-78" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "High" + category: "security" + pattern-either: + - pattern: "CreateProcessAsUser(...)" + - pattern: "CreateProcessWithLogon(...)" + severity: "WARNING" +- id: c_shell_rule-execl-execlp + languages: + - "c" + - "cpp" + - "cpp" + message: | + It is generally not recommended to call out to the operating system to execute commands. + When the application is executing file system based commands, user input should never be used + in + constructing commands or command arguments. If possible, determine if a library can be used + instead to provide the same functionality. Otherwise, consider hard coding both the command + and arguments to be used, or at the very least restricting which arguments can be passed + to the command execution function. + + Please see the compliant solutions in the following page: + https://wiki.sei.cmu.edu/confluence/pages/viewpage.action?pageId=87152177 + metadata: + shortDescription: "Potential for OS command injection" + cwe: "CWE-78" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "High" + category: "security" + pattern-either: + - pattern: "execl(...)" + - pattern: "execlp(...)" + - pattern: "execle(...)" + - pattern: "execv(...)" + - pattern: "execvp(...)" + - pattern: "popen(...)" + - pattern: "WinExec(...)" + - pattern: "ShellExecute(...)" + severity: "ERROR" +- id: c_shell_rule-system + languages: + - "c" + - "cpp" + - "cpp" + message: | + It is generally not recommended to call out to the operating system to execute commands. + When the application is executing file system based commands, user input should never be used + in + constructing commands or command arguments. If possible, determine if a library can be used + instead to provide the same functionality. Otherwise, consider hard coding both the command + and arguments to be used, or at the very least restricting which arguments can be passed + to the command execution function. + + For more information please see: + https://wiki.sei.cmu.edu/confluence/pages/viewpage.action?pageId=87152177 + metadata: + shortDescription: "Potential for OS command injection" + cwe: "CWE-78" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "High" + category: "security" + pattern: "system(...)" + severity: "ERROR" +- id: c_tmpfile_rule-GetTempFileName + languages: + - "c" + - "cpp" + - "cpp" + message: | + The `GetTempFileName` function works by generating a randomly named file, creating the file + (if it does not exist) and then closing it. An application wishing to use this temporary file + will need to reopen this file to begin working with it. This leads to a potential + Time Of Check Time Of Use (TOCTOU) vulnerability, as an attacker could replace or modify + the contents of the file prior to it being used by the application. + + Consider generating a random filename and opening the file directly in a single `CreateFile` + or `OpenFile` call. + metadata: + shortDescription: "Potential time of check time of use vulnerability (GetTempFileName)" + cwe: "CWE-377" + owasp: + - "A5:2017-Broken Access Control" + - "A01:2021-Broken Access Control" + security-severity: "Medium" + category: "security" + pattern: "GetTempFileName(...)" + severity: "WARNING" +- id: c_tmpfile_rule-mkstemp + languages: + - "c" + - "cpp" + - "cpp" + message: | + Some older Unix-like systems, `mkstemp` would create temp files with 0666 permissions, + meaning the file created would be read/write access for all users. + + Ensure the process has called the `umask` function with restricted permissions prior + to calling `mkstemp` and validate the permissions prior to using the file descriptor. + + For more information on temporary files please see: + https://wiki.sei.cmu.edu/confluence/pages/viewpage.action?pageId=87152425 + metadata: + shortDescription: "Potential file permissions issue (mkstemp)" + cwe: "CWE-377" + owasp: + - "A5:2017-Broken Access Control" + - "A01:2021-Broken Access Control" + security-severity: "Medium" + category: "security" + pattern: "mkstemp(...)" + severity: "INFO" +- id: c_tmpfile_rule-mktemp + languages: + - "c" + - "cpp" + - "cpp" + message: | + The `mktemp` function should no longer be used due to multiple flaws. Some implementations + created random files by using known information like the process ID and a single letter. This + allows for possible race conditions where an attacker could guess or manipulate these files + prior to them being used. + + Consider using the `mkstemp` function instead, but be aware it also contains possible + risks. Ensure the process has called the `umask` function with restricted permissions prior + to calling `mkstemp` and validate the permissions prior to using the file descriptor. + + For more information on temporary files please see: + https://wiki.sei.cmu.edu/confluence/pages/viewpage.action?pageId=87152425 + metadata: + shortDescription: "Use of deprecated function (mktemp)" + cwe: "CWE-377" + owasp: + - "A5:2017-Broken Access Control" + - "A01:2021-Broken Access Control" + security-severity: "Medium" + category: "security" + pattern: "mktemp(...)" + severity: "ERROR" +- id: c_tmpfile_rule-tmpfile + languages: + - "c" + - "cpp" + - "cpp" + message: | + There exists a possible race condition in between the time that `tmpfile` returns + a pathname, and the time that the program opens it, another program might create + that pathname using `open`, or create it as a symbolic link. + + Consider using the `mkstemp` function instead, but be aware it also contains possible + risks. Ensure the process has called the `umask` function with restricted permissions prior + to calling `mkstemp` and validate the permissions prior to using the file descriptor. + + For more information on temporary files please see: + https://wiki.sei.cmu.edu/confluence/pages/viewpage.action?pageId=87152425 + metadata: + shortDescription: "Potential time of check time of use vulnerability (tmpfile)" + cwe: "CWE-377" + owasp: + - "A5:2017-Broken Access Control" + - "A01:2021-Broken Access Control" + security-severity: "Medium" + category: "security" + pattern: "tmpfile(...)" + severity: "INFO" +- id: c_tmpfile_rule-tmpnam-tempnam + languages: + - "c" + - "cpp" + - "cpp" + message: | + There exists a possible race condition in between the time that `tempnam` or `tmpnam` + returns a pathname, and the time that the program opens it, another program might create + that pathname using `open`, or create it as a symbolic link. + + Consider using the `mkstemp` function instead, but be aware it also contains possible + risks. Ensure the process has called the `umask` function with restricted permissions prior + to calling `mkstemp` and validate the permissions prior to using the file descriptor. + + For more information on temporary files please see: + https://wiki.sei.cmu.edu/confluence/pages/viewpage.action?pageId=87152425 + metadata: + shortDescription: "Potential time of check time of use vulnerability (tmpnam/tempnam)" + cwe: "CWE-377" + owasp: + - "A5:2017-Broken Access Control" + - "A01:2021-Broken Access Control" + security-severity: "Medium" + category: "security" + pattern-either: + - pattern: "tmpnam(...)" + - pattern: "tempnam(...)" + severity: "WARNING" + + +- id: csharp_cookies_rule-CookieWithoutHttpOnlyFlag + languages: + - "csharp" + mode: "taint" + pattern-sources: + - pattern: | + var $COOKIE = new HttpCookie(...); + pattern-sinks: + - pattern: "$COOKIE" + pattern-sanitizers: + - pattern: "$COOKIE.HttpOnly = true;" + message: | + The `HttpOnly` attribute when set to `true` protects the cookie value from being accessed by + client side JavaScript such + as reading the `document.cookie` values. By enabling this protection, a website that is + vulnerable to + Cross-Site Scripting (XSS) will be able to block malicious scripts from accessing the cookie + value from JavaScript. + + Example of protecting an HttpCookie: + ``` + // Create an HttpOnly cookie. + HttpCookie someCookie = new HttpCookie("SomeCookieName", "SomeValue"); + someCookie.HttpOnly = true; + ``` + + For more information see: + https://learn.microsoft.com/en-us/dotnet/api/system.web.httpcookie.httponly + + Session cookies should be configured with the following security directives: + + - [HTTPOnly](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#restrict_access_to_cookies) + - [Secure](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#restrict_access_to_cookies) + - [SameSite](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite) + severity: "WARNING" + metadata: + shortDescription: "Sensitive cookie without 'HttpOnly' flag" + category: "security" + owasp: + - "A6:2017-Security Misconfiguration" + - "A05:2021-Security Misconfiguration" + cwe: "CWE-1004" + security-severity: "Low" +- id: csharp_cookies_rule-CookieWithoutSSLFlag + languages: + - "csharp" + mode: "taint" + pattern-sources: + - pattern: | + var $COOKIE = new HttpCookie(...); + pattern-sinks: + - pattern: "$COOKIE" + pattern-sanitizers: + - pattern: "$COOKIE.Secure = true;" + message: | + The `Secure` attribute when set to `true` protects the cookie value from being being + transmitted over clear text + communication paths such as HTTP. By enabling this protection, the cookie will only be sent + over HTTPS. + + Example of protecting an HttpCookie: + ``` + // Create an HttpOnly cookie. + HttpCookie someCookie = new HttpCookie("SomeCookieName", "SomeValue"); + someCookie.Secure = true; + ``` + + For more information see: + https://learn.microsoft.com/en-us/dotnet/api/system.web.httpcookie.secure + + Session cookies should be configured with the following security directives: + + - [HTTPOnly](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#restrict_access_to_cookies) + - [SameSite](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite) + - [Secure](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#restrict_access_to_cookies) + severity: "WARNING" + metadata: + shortDescription: "Sensitive cookie in HTTPS session without 'Secure' attribute" + category: "security" + owasp: + - "A6:2017-Security Misconfiguration" + - "A05:2021-Security Misconfiguration" + cwe: "CWE-614" + security-severity: "Low" +- id: csharp_crypto_rule-CertificateValidationDisabled + languages: + - "csharp" + patterns: + - pattern-inside: | + using System.Net; + ... + - pattern: "ServicePointManager.ServerCertificateValidationCallback += $CALLBACK;" + - metavariable-pattern: + metavariable: "$CALLBACK" + patterns: + - pattern-either: + - pattern: "$RETURNTYPE $FUNC(...) { return true; }" + - pattern: "(...) => true;" + message: | + The `ServicePointManager.ServerCertificateValidationCallback` event has been set + to always return `true`, which effectively disables the validation of server + certificates. + + This allows for an adversary who is in between the application and the target host to intercept + potentially sensitive information or transmit malicious data. + + Remove the callback function that is returning true to allow normal certificate validation to + proceed. + When no callback is provided, the client will validate that the certificate name matches the + hostname + that was used when creating the request. + + For more information on the `ServerCertificateValidationCallback` property see: + https://learn.microsoft.com/en-us/dotnet/api/system.net.servicepointmanager.servercertificatevalidationcallback + severity: "WARNING" + metadata: + shortDescription: "Certificate validation disabled" + category: "security" + owasp: + - "A2:2017-Broken Authentication" + - "A07:2021-Identification and Authentication Failures" + cwe: "CWE-295" + security-severity: "Medium" +- id: csharp_crypto_rule-WeakCipherAlgorithm + patterns: + - pattern-inside: | + using System.Security.Cryptography; + ... + - pattern-either: + - pattern-regex: ".*DES\\.Create\\(\\);" + - pattern: "new DESCryptoServiceProvider();" + - pattern-regex: ".*TripleDES\\.Create\\(\\);" + - pattern: "new TripleDESCryptoServiceProvider();" + - pattern-regex: ".*RC2\\.Create\\(\\);" + - pattern: "new RC2CryptoServiceProvider();" + message: | + DES, TripleDES and RC2 are all considered broken or insecure cryptographic algorithms. + If using .NET Framework greater than version 6.0 consider using `ChaCha20Poly1305` + instead as it is easier and faster than the alternatives such as `AES-256-GCM`. + + For older applications, `AES-256-GCM` is recommended, however it has many drawbacks: + - Slower than `ChaCha20Poly1305`. + - Catastrophic failure if nonce values are reused. + + Example using `ChaCha20Poly1305`: + ``` + // Generate a random key + byte[] key = new byte[32]; + RandomNumberGenerator.Fill(key); + + // Note nonce values _must_ be regenerated every time they are used. + byte[] nonce = new byte[12]; + RandomNumberGenerator.Fill(nonce); + + byte[] authTag = new byte[16]; + byte[] cipherText; + + using (ChaCha20Poly1305 encryptor = new ChaCha20Poly1305(key)) + { + byte[] plainText = System.Text.Encoding.UTF8.GetBytes("Secret text to encrypt"); + cipherText = new byte[plainText.Length]; + encryptor.Encrypt(nonce, plainText, cipherText, authTag); + } + + using (ChaCha20Poly1305 decryptor = new ChaCha20Poly1305(key)) + { + byte[] output = new byte[cipherText.Length]; + decryptor.Decrypt(nonce, cipherText, authTag, output); + Console.WriteLine("Output: {0}", System.Text.Encoding.UTF8.GetString(output)); + } + ``` + + Example using `AES-256-GCM`: + ``` + // Generate a random key + byte[] key = new byte[32]; + RandomNumberGenerator.Fill(key); + + // Note nonce values _must_ be regenerated every time they are used. + byte[] nonce = new byte[AesGcm.NonceByteSizes.MaxSize]; + RandomNumberGenerator.Fill(nonce); + + byte[] authTag = new byte[AesGcm.TagByteSizes.MaxSize]; + byte[] cipherText; + + using (AesGcm encryptor = new AesGcm(key)) + { + byte[] plainText = Encoding.UTF8.GetBytes("Secret text to encrypt"); + cipherText = new byte[plainText.Length]; + encryptor.Encrypt(nonce, plainText, cipherText, authTag); + } + + using (AesGcm decryptor = new AesGcm(key)) + { + byte[] output = new byte[cipherText.Length]; + decryptor.Decrypt(nonce, cipherText, authTag, output); + Console.WriteLine("Output: {0}", Encoding.UTF8.GetString(output)); + } + ``` + languages: + - "csharp" + severity: "WARNING" + metadata: + shortDescription: "Use of a broken or risky cryptographic algorithm" + category: "security" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + cwe: "CWE-327" + security-severity: "Medium" +- id: csharp_crypto_rule-WeakCipherMode + languages: + - "csharp" + patterns: + - pattern-inside: | + using System.Security.Cryptography; + ... + - metavariable-regex: + metavariable: "$CIPHER" + regex: "^(ECB|CBC|OFB|CFB|CTS)$" + - pattern: "CipherMode.$CIPHER" + message: | + Cryptographic algorithms provide many different modes of operation, only some of which provide + message integrity. Without message integrity it could be possible for an adversary to attempt + to tamper with the ciphertext which could lead to compromising the encryption key. Newer + algorithms + apply message integrity to validate ciphertext has not been tampered with. + + Instead of using an algorithm that requires configuring a `CipherMode`, an algorithm + that has built-in message integrity should be used. If using .NET Framework greater + than version 6.0 consider using `ChaCha20Poly1305` or `AES-256-GCM`. + + For older applications, `AES-256-GCM` is recommended, however it has many drawbacks: + - Slower than `ChaCha20Poly1305`. + - Catastrophic failure if nonce values are re-used. + + Example using `ChaCha20Poly1305`: + ``` + // Generate a random key + byte[] key = new byte[32]; + RandomNumberGenerator.Fill(key); + + ChaCha20Poly1305 encryptor = new ChaCha20Poly1305(key); + + // Note nonce values _must_ be regenerated every time they are used. + var nonce = new byte[12]; + RandomNumberGenerator.Fill(nonce); + + byte[] plainText = System.Text.Encoding.UTF8.GetBytes("Secret text to encrypt"); + byte[] cipherText = new byte[plainText.Length]; + var authTag = new byte[16]; + + encryptor.Encrypt(nonce, plainText, cipherText, authTag); + byte[] output = new byte[cipherText.Length]; + encryptor.Decrypt(nonce, cipherText, authTag, output); + Console.WriteLine("Output: {0}", System.Text.Encoding.UTF8.GetString(output)); + ``` + + Example using `AES-256-GCM`: + ``` + var plaintextBytes = Encoding.UTF8.GetBytes("Secret text to encrypt"); + var key = new byte[32]; + RandomNumberGenerator.Fill(key); + + using var aes = new AesGcm(key); + var nonce = new byte[AesGcm.NonceByteSizes.MaxSize]; + RandomNumberGenerator.Fill(nonce); + + var cipherText = new byte[plaintextBytes.Length]; + var tag = new byte[AesGcm.TagByteSizes.MaxSize]; + + aes.Encrypt(nonce, plaintextBytes, cipherText, tag); + + // Decrypt + using (var decrypt = new AesGcm(key)) + { + var decryptedBytes = new byte[cipherText.Length]; + + decrypt.Decrypt(nonce, cipherText, tag, decryptedBytes); + + Console.WriteLine("Decrypted: {0}", Encoding.UTF8.GetString(decryptedBytes)); + } + ``` + severity: "WARNING" + metadata: + shortDescription: "Use of a broken or risky cryptographic algorithm" + category: "security" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + cwe: "CWE-327" + security-severity: "Medium" +- id: csharp_crypto_rule-WeakHashingFunction + languages: + - "csharp" + patterns: + - pattern-either: + - patterns: + - metavariable-regex: + metavariable: "$HASH_PROVIDER" + regex: "^(SHA1CryptoServiceProvider|MD5CryptoServiceProvider)$" + - pattern: "new $HASH_PROVIDER" + - patterns: + - metavariable-regex: + metavariable: "$HASH_CLASS" + regex: "^System.Security.Cryptography.(SHA1|MD5)$" + - pattern: "$HASH_CLASS.$METHOD();" + message: | + Both MD5 and SHA1 hash algorithms have been found to be vulnerable to producing collisions. + This means + that two different values, when hashed, can lead to the same hash value. If the application is + trying + to use these hash methods for storing passwords, then it is recommended to switch to a + password hashing + algorithm such as Argon2id or PBKDF2. Currently there is no vetted Argon2id implementation for + C# so + it is recommended that PBKDF2 be used until one is available. + + Example using PBKDF2 to generate and compare passwords: + ``` + const int SaltSize = 24; + const int HashSize = 24; + // number of pbkdf2 iterations, Rfc2898DeriveBytes uses hmac-sha1 + // so set a high iteration count + const int Iterations = 1_300_000; + byte[] salt = new byte[SaltSize]; + RandomNumberGenerator.Fill(salt); + + Rfc2898DeriveBytes pbkdf2 = new Rfc2898DeriveBytes("some password", salt, Iterations); + byte[] hashBytes = pbkdf2.GetBytes(HashSize); + // Store salt and hashedBytes in a data store such as database for authentication + Console.WriteLine("Hash {0}", BitConverter.ToString(hashBytes).Replace("-", "")); + // Do a constant time comparison as to not leak data based on timing + if (CryptographicOperations.FixedTimeEquals(hashBytes, hashBytes)) { + Console.WriteLine("hashes are equal"); + } + ``` + For more information on PBKDF2 see: + https://learn.microsoft.com/en-us/dotnet/api/system.security.cryptography.rfc2898derivebytes + + For more information on secure password storage see OWASP: + https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html + severity: "WARNING" + metadata: + shortDescription: "Use of a broken or risky cryptographic algorithm (SHA1/MD5)" + category: "security" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + cwe: "CWE-327" + security-severity: "Medium" +- id: csharp_crypto_rule-WeakRNG + languages: + - "csharp" + patterns: + - pattern: "(Random $RNG).$METHOD(...);" + - focus-metavariable: "$RNG" + message: | + Depending on the context, generating weak random numbers may expose cryptographic functions + which rely on these numbers to be exploitable. When generating numbers for sensitive values + such as tokens, nonces, and cryptographic keys, it is recommended that the + `RandomNumberGenerator` class be used. + + Example `RandomNumberGenerator` usage: + ``` + Int32 randInt = RandomNumberGenerator.GetInt32(32000); + byte[] randomBytes = new byte[64]; + RandomNumberGenerator.Fill(randomBytes); + Console.WriteLine("Random Int32: {0}", randInt); + Console.WriteLine("Random Bytes: {0}", BitConverter.ToString(randomBytes).Replace("-", "")); + ``` + + For more information see: + https://learn.microsoft.com/en-us/dotnet/api/system.security.cryptography.randomnumbergenerator + severity: "WARNING" + metadata: + shortDescription: "Use of cryptographically weak Pseudo-Random Number Generator + (PRNG)" + category: "security" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + cwe: "CWE-338" + security-severity: "Medium" +- id: csharp_csrf_rule-Csrf + languages: + - "csharp" + patterns: + - pattern: | + [$HTTPMETHOD] + public $RET $FOO(...) { + ... + } + - pattern-not: | + [ValidateAntiForgeryToken] + public $RET $FOO(...) { + ... + } + - pattern-not-inside: | + [AutoValidateAntiforgeryToken] + class $CLASS{ + ... + } + - pattern-not-inside: | + [ValidateAntiForgeryToken] + class $CLASS{ + ... + } + - metavariable-regex: + metavariable: "$HTTPMETHOD" + regex: "Http(Post|Delete|Patch|Put)" + message: | + The application failed to protect against Cross-Site Request Forgery (CSRF) + due to not including the `[ValidateAntiForgeryToken]` attribute on an + HTTP method handler that could change user state (usually in the form of POST or PUT + methods). + + The vulnerability can be exploited by an adversary creating a link or form on a third + party site and tricking an authenticated victim to access them. + + Add the `[ValidateAntiForgeryToken]` to all methods which take in user data and change + user state (such as updating a database with a new value). This is especially true for + functionality such as updating passwords or other security sensitive functions. + + Alternatively, applications can enable a global + [AutoValidateAntiforgeryTokenAttribute](https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.autovalidateantiforgerytokenattribute) + filter. + + For more information on ValidateAntiForgeryToken and other CSRF protections in .NET + see the following URL: + https://learn.microsoft.com/en-us/aspnet/core/security/anti-request-forgery + + Additionally, consider setting all session cookies to have the `SameSite=Strict` attribute. + It should be noted that this may impact usability when sharing links across other mediums. + It is recommended that a two cookie based approach is taken, as outlined in the + [Top level + navigations](https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis-08#section-8.8.2) + section + of the SameSite RFC. + + For more information on CSRF see OWASP's guide: + https://owasp.org/www-community/attacks/csrf + severity: "WARNING" + metadata: + shortDescription: "Potential Cross-Site Request Forgery (CSRF)" + category: "security" + owasp: + - "A5:2017-Broken Access Control" + - "A01:2021-Broken Access Control" + cwe: "CWE-352" + security-severity: "Medium" +- id: csharp_deserialization_rule-InsecureDeserialization + mode: "taint" + pattern-sources: + - pattern: "Request.Cookies[...]" + - pattern: "Request.Cookies.Get(...)" + - pattern: "Request.Form[...]" + - pattern: "Request.Form.Get(...)" + - pattern: "Request.Headers[...]" + - pattern: "Request.Headers.Get(...)" + - pattern: "Request.QueryString[...]" + - pattern: "Request.QueryString.Get(...)" + - pattern: "Request.Body" + - pattern: "$CTX.Request.Cookies[...]" + - pattern: "$CTX.Request.Cookies.Get(...)" + - pattern: "$CTX.Request.Form[...]" + - pattern: "$CTX.Request.Form.Get(...)" + - pattern: "$CTX.Request.Headers[...]" + - pattern: "$CTX.Request.Headers.Get(...)" + - pattern: "$CTX.Request.QueryString[...]" + - pattern: "$CTX.Request.QueryString.Get(...)" + - pattern: "$CTX.Request.Body" + - pattern: "System.IO.File.ReadAllText(...)" + - pattern: "System.IO.File.ReadAllTextAsync(...)" + - pattern: "System.IO.File.ReadAllLines(...)" + - pattern: "System.IO.File.ReadAllLinesAsync(...)" + - pattern: "System.IO.File.ReadAllBytes(...)" + - pattern: "System.IO.File.ReadAllBytesAsync(...)" + - pattern: "System.IO.File.ReadLines(...)" + - pattern: "System.IO.File.ReadLinesAsync(...)" + - pattern: "System.Environment.GetEnvironmentVariable(...)" + pattern-sinks: + - pattern: "(System.Runtime.Serialization.Formatters.Binary.BinaryFormatter $OBJ).Deserialize(...)" + - pattern: "(System.Runtime.Serialization.Formatters.Binary.BinaryFormatter $OBJ).UnsafeDeserialize(...)" + - pattern: "(System.Runtime.Serialization.Formatters.Binary.BinaryFormatter $OBJ).UnsafeDeserializeMethod(...)" + - pattern: "(System.Runtime.Serialization.Formatters.Soap.SoapFormatter $OBJ).Deserialize(...)" + - pattern: "(System.Runtime.Serialization.NetDataContractSerializer $OBJ).Deserialize(...)" + - pattern: "(System.Web.UI.LosFormatter $OBJ).Deserialize(...)" + languages: + - "csharp" + message: | + Deserialization attacks exploit the process of reading serialized data and turning it back into an + object. By constructing malicious objects and serializing them, an adversary may attempt to: + + - Inject code that is executed upon object construction, which occurs during the deserialization process. + - Exploit mass assignment by including fields that are not normally a part of the serialized data but are + read in during deserialization. + + Microsoft recommends no longer using the following serialization formats: + + - BinaryFormatter + - SoapFormatter + - NetDataContractSerializer + - LosFormatter + - ObjectStateFormatter + + Consider safer alternatives such as serializing data in the JSON format. Ensure any format chosen allows + the application to specify exactly which object types are allowed to be deserialized. Additionally, when + deserializing, never deserialize to base object types like `Object` and only cast to the exact object + type that is expected. + + To protect against mass assignment, only allow deserialization of the specific fields that are required. + If this is not easily done, consider creating an intermediary type that can be serialized with only the + necessary fields exposed. + + For more information see Microsoft's deserialization security guide: + https://learn.microsoft.com/en-us/dotnet/standard/serialization/binaryformatter-security-guide + + For more details on deserialization attacks in general, see OWASP's guide: + https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html + + It should be noted that [tools exist](https://github.com/pwntester/ysoserial.net) to automatically create + exploit code for these vulnerabilities. + metadata: + shortDescription: "Deserialization of potentially untrusted data" + category: "security" + cwe: "CWE-502" + owasp: + - "A8:2017-Insecure Deserialization" + - "A08:2021-Software and Data Integrity Failures" + security-severity: "High" + severity: "WARNING" +- id: csharp_endpoint_rule-UnvalidatedRedirect + languages: + - "csharp" + mode: "taint" + pattern-sources: + - patterns: + - pattern: "$SRC" + - pattern-inside: | + public $RET $FUNC(...,$SRC,...){...} + - patterns: + - pattern: "$SRC" + - pattern-inside: | + if (Uri.TryCreate(..., ..., $SRC)){ + ... + } + pattern-sanitizers: + - pattern: "Url.Action(...)" + - pattern: "Url.HttpRouteUrl(...)" + - pattern: "Url.RouteUrl(...)" + pattern-sinks: + - patterns: + - pattern-either: + - patterns: + - pattern-either: + - pattern: "return $METHOD(...)" + - pattern: "return new $METHOD(...)" + - pattern: | + if (!Url.IsLocalUrl(...)) { + ... + return $METHOD(...) + } + - patterns: + - pattern-not-inside: | + if (Url.IsLocalUrl(...)) { + ... + } + - pattern-not-inside: | + if (!Url.IsLocalUrl(...)) { + return $X + } + ... + - pattern-either: + - pattern: "$METHOD(...)" + - pattern: "new $METHOD(...)" + - metavariable-pattern: + metavariable: "$METHOD" + pattern-either: + - pattern: "Redirect" + - pattern: "RedirectPermanent" + - pattern: "RedirectToRoute" + - pattern: "RedirectToRoutePermanent" + - pattern: "RedirectResult" + message: | + The application may allow open redirects if created using user supplied input. Open redirects + are + commonly + abused in phishing attacks where the original domain or URL looks like a legitimate link, but + then + redirects a user to a malicious site. An example would be + `https://example.com/redirect?url=https://%62%61%64%2e%63%6f%6d%2f%66%61%6b%65%6c%6f%67%69%6e` + which, + when decoded, turns into `bad.com/fakelogin`. + + Never redirect a client based on user input. It is recommended that the list of target links + to + redirect a user to are contained server side, and retrieved using a numerical value + as an index to return the link to be redirected to. For example, `/redirect?id=1` would cause + the + application to look up the `1` index and return a URL such as `https://example.com`. This URL + would + then be used to redirect the user, using the 301 response code and `Location` header. + + For more information on open redirects see OWASP's guide: + https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html + metadata: + shortDescription: "URL redirection to untrusted site 'open redirect'" + category: "security" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + cwe: "CWE-601" + security-severity: "Info" + severity: "WARNING" +- id: csharp_injection_rule-CommandInjection + languages: + - "csharp" + patterns: + - pattern-either: + - patterns: + - pattern-inside: | + ... + (System.Diagnostics.Process $PROC).Start(...); + - pattern-either: + - patterns: + - pattern: "(System.Diagnostics.Process $PROC).StartInfo.FileName = <...$ARG...>;" + - pattern-not: "(System.Diagnostics.Process $PROC).StartInfo.FileName = + \"...\";" + - patterns: + - pattern: "(System.Diagnostics.Process $PROC).StartInfo.Arguments = <...$ARG...>;" + - pattern-not: "(System.Diagnostics.Process $PROC).StartInfo.Arguments = + \"...\";" + - patterns: + - pattern: "System.Diagnostics.Process.Start($ARG);" + - pattern-not: "System.Diagnostics.Process.Start(\"...\");" + - patterns: + - pattern-not: "$PSINFO.Arguments = \"...\";" + - pattern-not: "$PSINFO.FileName = \"...\";" + - pattern-not: "new System.Diagnostics.ProcessStartInfo(\"...\");" + - pattern-not: "new System.Diagnostics.ProcessStartInfo();" + - pattern-either: + - pattern: "new System.Diagnostics.ProcessStartInfo(...);" + - pattern: "$PSINFO.Arguments = <...$ARG...>;" + - pattern: "$PSINFO.FileName = <...$ARG...>;" + - patterns: + - pattern-inside: | + new System.Diagnostics.ProcessStartInfo{ + ... + } + - pattern-not: "Arguments = \"...\"" + - pattern-not: "FileName = \"...\"" + - pattern-either: + - pattern: "Arguments = ..." + - pattern: "FileName = ..." + message: | + OS command injection is a critical vulnerability that can lead to a full system + compromise as it may allow an adversary to pass in arbitrary commands or arguments + to be executed. + + User input should never be used in constructing commands or command arguments + to functions which execute OS commands. This includes filenames supplied by + user uploads or downloads. + + Ensure your application does not: + + - Use user-supplied information in the process name to execute. + - Use user-supplied information in an OS command execution function which does + not escape shell meta-characters. + - Use user-supplied information in arguments to OS commands. + + The application should have a hardcoded set of arguments that are to be passed + to OS commands. If filenames are being passed to these functions, it is + recommended that a hash of the filename be used instead, or some other unique + identifier. It is strongly recommended that a native library that implements + the same functionality be used instead of using OS system commands, due to the + risk of unknown attacks against third party commands. + + When specifying the OS command, ensure the application uses the full path + information, otherwise the OS may attempt to look up which process to execute + and could be vulnerable to untrusted search path vulnerabilities (CWE-426). + + Example of safely executing an OS command: + ``` + public void ExecuteCommand(string userFileData) { + // generate a random filename, do not using user input + string fileName = "C:\\Temp\\" + Guid.NewGuid(); + File.WriteAllText(fileName, userFileData); + + using (Process process = new Process()) + { + // hardcode the full process path + ProcessStartInfo processInfo = new ProcessStartInfo("C:\\App\\FileReader.exe"); + // only pass in trust arguments, and never direct user input. + processInfo.Arguments = fileName; + processInfo.UseShellExecute = false; + process.StartInfo = processInfo; + process.Start(); + } + } + ``` + + For more information on OS command injection, see OWASP's guide: + https://cheatsheetseries.owasp.org/cheatsheets/OS_Command_Injection_Defense_Cheat_Sheet.html + severity: "ERROR" + metadata: + shortDescription: "Improper neutralization of special elements used in an OS command + ('OS Command Injection')" + category: "security" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + cwe: "CWE-78" + security-severity: "High" +- id: csharp_injection_rule-LdapInjection + languages: + - "csharp" + mode: taint + pattern-sources: + - patterns: + - pattern-inside: | + $RET $METHOD(...,$VAR,...){...} + - pattern: "$VAR" + pattern-sinks: + - pattern: "System.DirectoryServices.AccountManagement.UserPrincipal.FindByIdentity(...)" + - pattern: "new System.DirectoryServices.DirectoryEntry(...)" + - pattern: "new System.DirectoryServices.DirectorySearcher(...)" + - pattern: "new System.DirectoryServices.Protocols.SearchRequest(...)" + - patterns: + - focus-metavariable: $TAINTED + - pattern-either: + - pattern: "(System.DirectoryServices.DirectoryEntry $SOURCE).Path = $TAINTED" + - pattern: "(System.DirectoryServices.DirectorySearcher $SEARCHER).Filter = $TAINTED" + - pattern: "(System.DirectoryServices.Protocols.SearchRequest $SEARCHREQ).Filter = $TAINTED" + - pattern: "(System.DirectoryServices.Protocols.SearchRequest $SEARCHREQ).DistinguishedName = $TAINTED" + - pattern: "(System.DirectoryServices.AccountManagement.UserPrincipal $SEARCHREQ).$PROP = $TAINTED" + message: | + LDAP injection attacks exploit LDAP queries to influence how data is returned by + the LDAP, or in this case an Active Directory server. + + It is recommended that newer applications use the `System.DirectoryServices.AccountManagement` + API instead of `DirectorySearcher` API as it hides the complexity of querying LDAP directly. + However, + the `AccountManagement` API is still susceptible to LDAP injection if a user inputs LDAP + queries, + including LDAP filter characters such as `*`. + + It is recommended that all input passed to LDAP querying systems encode the following values: + + - Any occurrence of the null character must be escaped as “\00”. + - Any occurrence of the open parenthesis character must be escaped as “\28”. + - Any occurrence of the close parenthesis character must be escaped as “\29”. + - Any occurrence of the asterisk character must be escaped as “\2a”. + - Any occurrence of the backslash character must be escaped as “\5c”. + + Example code that safely encodes input for use in an LDAP query using the `AccountManagement` + API: + ``` + using System.DirectoryServices.AccountManagement; + + string EncodeLDAPString(string input) { + // Note the \ character is replaced first + char[] chars = new char[] { '\\', '\0', '(', ')', '*' }; + string[] encoded = new string[] { "\\5c", "\\00", "\\28", "\\29", "\\2a" }; + + for (int i = 0; i < chars.Length; i++) + { + input = input.Replace(chars[i].ToString(), encoded[i]); + } + + return input; + } + + // unsafe, do not use without encoding first + string userInput = "Administrator"; + PrincipalContext AD = new PrincipalContext(ContextType.Domain, "ad.example.dev"); + + UserPrincipal u = new UserPrincipal(AD); + string encodedUserName = EncodeLDAPString(userInput); + + // The AD search term, encoded prior to calling search + u.SamAccountName = encodedUserName; + + // Search for user + PrincipalSearcher search = new PrincipalSearcher(u); + + // Use FindOne to only return a single result + UserPrincipal result = (UserPrincipal)search.FindOne(); + search.Dispose(); + + // show some details + if (result != null) { + Console.WriteLine("User: {0}", result.DisplayName); + } else { + Console.WriteLine("user not found"); + } + ``` + + The same encoding method shown in `EncodeLDAPString` can also be used when using the + older `DirectorySearcher` API. + + For more information see OWASP's guide: + https://cheatsheetseries.owasp.org/cheatsheets/LDAP_Injection_Prevention_Cheat_Sheet.html + severity: "WARNING" + metadata: + shortDescription: "Improper neutralization of special elements used in an LDAP + query ('LDAP Injection')" + category: "security" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + cwe: "CWE-90" + security-severity: "Medium" +- id: csharp_injection_rule-SQLInjection + languages: + - "csharp" + patterns: + - pattern-either: + - patterns: + - metavariable-pattern: + metavariable: "$FUNC" + pattern-either: + - pattern: "SqlQuery" + - pattern: "ExecuteSqlCommand" + - pattern: "ExecuteSqlCommandAsync" + - pattern: "ExecuteSqlRaw" + - pattern: "ExecuteSqlRawAsync" + - pattern: "FromSqlRaw" + - pattern: "FromSql" + - pattern: "GetSqlStringCommand" + - pattern: "ExecuteDataSet" + - pattern: "ExecuteReader" + - pattern: "ExecuteNonQuery" + - pattern: "ExecuteScalar" + - pattern: "CreateSQLQuery" + - pattern-either: + - pattern: "$DB.$FUNC($ARG, ...)" + - pattern: "$DB.$FUNC<$CC>($ARG, ...)" + - pattern-not: "$DB.$FUNC(\"...\", ...)" + - pattern-not: "$DB.$FUNC<$CC>(\"...\", ...)" + - patterns: + - pattern-inside: | + using System.Data.Linq; + ... + - pattern-either: + - patterns: + - pattern: "(DataContext $CTX).ExecuteQuery<$TRESULT>($ARG, ...)" + - pattern-not: "(DataContext $CTX).ExecuteQuery<$TRESULT>(\"...\", ...)" + - patterns: + - pattern: "(DataContext $CTX).ExecuteQuery($TYPE, $ARG, ...)" + - pattern-not: "(DataContext $CTX).ExecuteQuery($TYPE, \"...\", ...)" + - patterns: + - pattern: "(DataContext $CTX).ExecuteCommand($ARG, ...)" + - pattern-not: "(DataContext $CTX).ExecuteCommand(\"...\", ...)" + - patterns: + - metavariable-pattern: + metavariable: "$IMPL" + pattern-either: + - pattern: "SqlCommand" + - pattern: "OracleCommand" + - pattern: "NpgsqlCommand" + - pattern: "MySqlCommand" + - pattern: "EntityCommand" + - pattern: "OdbcCommand" + - pattern: "OleDbCommand" + - pattern: "SqliteCommand" + - pattern-either: + - patterns: + - pattern: "new $IMPL($ARG, ...);" + - pattern-not: "new $IMPL(\"...\", ...);" + - patterns: + - pattern: "($IMPL $CMD).CommandText = <...$ARG...>;" + - pattern-not: "($IMPL $CMD).CommandText = \"...\";" + - patterns: + - metavariable-pattern: + metavariable: "$FUNC" + pattern-either: + - pattern: "ExecuteDataRow" + - pattern: "ExecuteDataRowAsync" + - pattern: "ExecuteDataset" + - pattern: "ExecuteDatasetAsync" + - pattern: "ExecuteNonQuery" + - pattern: "ExecuteNonQueryAsync" + - pattern: "ExecuteReader" + - pattern: "ExecuteReaderAsync" + - pattern: "ExecuteScalar" + - pattern: "ExecuteScalarAsync" + - pattern: "UpdateDataSet" + - pattern: "UpdateDataSetAsync" + - pattern-inside: | + using MySql.Data.MySqlClient; + ... + - pattern: "MySqlHelper.$FUNC($CONN, $ARG, ...)" + - pattern-not: "MySqlHelper.$FUNC($CONN, \"...\", ...)" + - patterns: + - pattern-inside: | + using Cassandra; + ... + - pattern-not: "$SESS.Execute(\"...\", ...)" + - pattern-either: + - pattern: "(Session $SESS).Execute($ARG, ...)" + - patterns: + - pattern-inside: | + var $SESS = $CLUSTER.Connect(...); + ... + - pattern: "$SESS.Execute($ARG, ...)" + message: | + SQL Injection is a critical vulnerability that can lead to data or system compromise. By + dynamically generating SQL query strings, user input may be able to influence the logic of + the SQL statement. This could lead to an adversary accessing information they should + not have access to, or in some circumstances, being able to execute OS functionality or code. + + Replace all dynamically generated SQL queries with parameterized queries. In situations where + dynamic queries must be created, never use direct user input, but instead use a map or + dictionary of valid values and resolve them using a user supplied key. + + For example, some database drivers do not allow parameterized queries for `>` or `<` comparison + operators. In these cases, do not use a user supplied `>` or `<` value, but rather have the + user + supply a `gt` or `lt` value. The alphabetical values are then used to look up the `>` and `<` + values to be used in the construction of the dynamic query. The same goes for other queries + where + column or table names are required but cannot be parameterized. + + Example using parameterized queries with `SqlCommand`: + ``` + string userInput = "someUserInput"; + string connectionString = ...; + using (SqlConnection connection = new SqlConnection(connectionString)) + { + connection.Open(); + String sql = "SELECT name, value FROM table where name=@Name"; + + using (SqlCommand command = new SqlCommand(sql, connection)) + { + command.Parameters.Add("@Name", System.Data.SqlDbType.NVarChar); + command.Parameters["@Name"].Value = userInput; + using (SqlDataReader reader = command.ExecuteReader()) + { + while (reader.Read()) + { + Console.WriteLine("{0} {1}", reader.GetString(0), reader.GetString(1)); + } + } + } + } + ``` + + For more information on SQL Injection see OWASP: + https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html + severity: "WARNING" + metadata: + shortDescription: "Improper Neutralization of Special Elements used in an SQL + Command ('SQL Injection')" + category: "security" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + cwe: "CWE-89" + security-severity: "Medium" +- id: csharp_injection_rule-XPathInjection + languages: + - "csharp" + patterns: + - pattern-inside: | + using System.Xml; + ... + - pattern-either: + - patterns: + - metavariable-regex: + metavariable: "$FUNC" + regex: "^(SelectNodes|SelectSingleNode|Compile|Evaluate|Matches|Select|SelectAncestors|SelectChildren|SelectDescendants)$" + - metavariable-regex: + metavariable: "$TY" + regex: "^(XPathNavigator|XmlDocument|XmlNode|XmlDocumentXPathExtensions)$" + - pattern: "($TY $VAR).$FUNC(<...$ARG...>, ...)" + - pattern-not: "($TY $VAR).$FUNC(\"...\", ...)" + - patterns: + - pattern-inside: | + using System.Xml.Linq; + ... + - metavariable-regex: + metavariable: "$FUNC" + regex: "^(XPathEvaluate|XPathSelectElement|XPathSelectElements)$" + - pattern: "$VAR.$FUNC(<...$ARG...>, ...)" + - pattern-not: "$VAR.$FUNC(\"...\", ...)" + - patterns: + - pattern-inside: | + using System.Xml.Schema; + ... + - pattern-either: + - patterns: + - pattern: "$VAR.XPath = <...$ARG...>;" + - pattern-not: "$VAR.XPath = \"...\"" + - patterns: + - pattern: "new XmlSchemaXPath { XPath = <...$ARG...> };" + - focus-metavariable: "$ARG" + message: | + XPath injection is a vulnerability that can allow an adversary to inject or modify how an XML + query + is structured. Depending on the logic of the original query, this could lead to adversaries + extracting unauthorized information or in rare cases bypassing authorization checks. + + It is recommended that LINQ to XML is used instead of XPath for querying XML documents. Care + must be taken to **not** call these LINQ functions with user input as they can still lead to + XPath + injection: + + - `XPathEvaluate` + - `XPathSelectElement` + - `XPathSelectElements` + + Example using LINQ to XML to safely extract the first user from a list of users: + ``` + // XDocument is safe from XXE attacks as the resolver is disabled by default + XDocument doc = XDocument.Load("users.xml"); + XNamespace ns = "urn:users-schema"; + + string userInput = "LastName"; + + // Get all the users. + var user = doc.Descendants(ns + "user") + .Select(u => new { + FirstName = (string)u.Element(ns + "first-name"), + LastName = (string)u.Element(ns + "last-name") + }).Where(u => u.LastName == userInput).FirstOrDefault(); + + Console.WriteLine(user.FirstName + " " + user.LastName); + ``` + + For more information on LINQ to XML security see: + https://learn.microsoft.com/en-us/dotnet/standard/linq/linq-xml-security + + For more information on XML security see OWASP's guide: + https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#net + severity: "INFO" + metadata: + shortDescription: "Improper neutralization of data within XPath expressions ('XPath + Injection')" + category: "security" + cwe: "CWE-643" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "Medium" +- id: csharp_injection_rule-XmlDocumentXXEInjection + languages: + - "csharp" + mode: "taint" + pattern-sinks: + - patterns: + - pattern-not-inside: | + (XmlDocument $DOC).XmlResolver = null; + ... + - pattern-either: + - pattern: "(XmlDocument $DOC).Load(...);" + - pattern: "(XmlDocument $DOC).LoadXml(...);" + pattern-sources: + - pattern: "var $DOC = new System.Xml.XmlDocument(...);" + - patterns: + - pattern: "var $DOC = new System.Xml.XmlDocument {...};" + - pattern-not: "var $DOC = new System.Xml.XmlDocument {...,XmlResolver = null,...};" + message: | + External XML entities are a feature of XML parsers that allow documents to contain references + to + other documents or data. This feature can be abused to read files, communicate with external + hosts, + exfiltrate data, or cause a Denial of Service (DoS). + + XML parsers and document loaders must be configured to not resolve entities. This can be done + by: + - Ensuring you are running a version of .NET Framework greater than 4.5.2 (released in 2014). + - Using `XDocument` which disables entity resolution and is generally safe from DoS. + - Setting `XmlDocument`'s `XmlResolver` to null. + + Example of safely loading an XML file using `XmlDocument`: + ``` + XmlDocument document = new XmlDocument(); + document.XmlResolver = null; + document.Load("users.xml"); + ``` + + For more information on XML security, see OWASP's guide: + https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#net + severity: "WARNING" + metadata: + shortDescription: "Improper restriction of XML external entity reference ('XXE')" + category: "security" + cwe: "CWE-611" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "Medium" +- id: csharp_injection_rule-XmlReaderXXEInjection + languages: + - "csharp" + mode: "taint" + pattern-sinks: + - patterns: + - pattern-either: + - pattern-inside: | + $SETTINGS.ProhibitDtd = false; + ... + - pattern-inside: | + $SETTINGS.DtdProcessing = DtdProcessing.Parse; + ... + - pattern: "System.Xml.XmlReader.Create(..., $SETTINGS);" + pattern-sources: + - pattern: "var $SETTINGS = new XmlReaderSettings();" + message: | + External XML entities are a feature of XML parsers that allow documents to contain references + to + other documents or data. This feature can be abused to read files, communicate with external + hosts, + exfiltrate data, or cause a Denial of Service (DoS). + + XML parsers and document loaders must be configured to not resolve entities. This can be done + by: + - Ensuring you are running a version of .NET Framework greater than 4.5.2 (released in 2014). + - Setting `XmlTextReader`'s `ProhibitDtd` to `true` + - Setting `XmlReaderSettings` `DtdProcessing` to `DtdProcessing.Prohibit` + + Example of safely loading an XML file using `XmlDocument`: + ``` + var settings = new XmlReaderSettings(); + settings.DtdProcessing = DtdProcessing.Prohibit; + XmlReader reader = XmlReader.Create(path, settings); + ``` + + For more information on XML security, see OWASP's guide: + https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#net + severity: "WARNING" + metadata: + shortDescription: "Improper restriction of XML external entity reference ('XXE')" + category: "security" + cwe: "CWE-611" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "MEDIUM" +- id: csharp_other_rule-UnsafeXSLTSettingUsed + patterns: + - pattern-either: + - patterns: + - pattern: "new XsltSettings() {...,$OPTIONS,...};" + - metavariable-pattern: + metavariable: "$OPTIONS" + pattern-either: + - pattern: "EnableDocumentFunction = true" + - pattern: "EnableScript = true" + - patterns: + - pattern: "$SETTINGS.$OPT = true;" + - pattern: | + var $SETTINGS = new XsltSettings(); + ... + $SETTINGS.$OPT = true; + - metavariable-pattern: + metavariable: "$OPT" + pattern-either: + - pattern: "EnableDocumentFunction" + - pattern: "EnableScript" + message: | + By setting `XsltSettings.EnableScript` to true, an adversary who is able to influence the + loaded + XSL document could directly inject code to compromise the system. It is strongly + recommended that an alternative approach is used to work with XML data. + + For increased security: + + - Never process user-supplied XSL style sheets + - Ensure `XsltSettings.EnableScript` is set to false + - Ensure `XsltSettings.EnableDocumentFunction` is set to false + + If the application must calculate values from XML input, instead of using XSL scripts to + execute functions, modify the XML document prior to running the + `XslCompiledTransform.Transform` method. + + Example of modifying the XML prior to running `Transform`: + ``` + const String filename = "number.xml"; + const String stylesheet = "calc.xsl"; + + // Compile the style sheet. + XsltSettings xslt_settings = new XsltSettings(); + xslt_settings.EnableScript = false; // disable script + xslt_settings.EnableDocumentFunction = false; // disable document() function + XslCompiledTransform xslt = new XslCompiledTransform(); + XmlResolver resolver = null; // set a null entity resolver + xslt.Load(stylesheet, xslt_settings, resolver); + + // Load the XML source file, using XDocument for safety + XDocument doc = XDocument.Load(filename); + + // do our modifications to the document before the transformation + // instead of inside of a script. + doc.Element("data").Add(new XElement("circle", new XElement("radius", 12))); + + // Create an XmlWriter. + XmlWriterSettings settings = new XmlWriterSettings(); + settings.OmitXmlDeclaration = true; + settings.Indent = true; + XmlWriter writer = XmlWriter.Create("output.xml", settings); + // Finally, execute the transformation. + xslt.Transform(doc.CreateReader(), writer); + writer.Close(); + ``` + + For more information on security considerations when using XSL see the following URLs: + - https://learn.microsoft.com/en-us/dotnet/standard/data/xml/xslt-security-considerations + - https://learn.microsoft.com/en-us/dotnet/api/system.xml.xsl.xslcompiledtransform?view=net-7.0#security-considerations + languages: + - "csharp" + severity: "WARNING" + metadata: + shortDescription: "XML injection (aka Blind XPath injection)" + category: "security" + cwe: "CWE-91" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "High" +- id: csharp_password_rule-PasswordComplexity + languages: + - "csharp" + pattern-either: + - pattern: "$OPT.Password.RequireDigit = false;" + - pattern: "$OPT.Password.RequireLowercase = false;" + - pattern: "$OPT.Password.RequireNonAlphanumeric = false;" + - pattern: "$OPT.Password.RequireUppercase = false;" + - patterns: + - pattern: "$OPT.Password.RequiredLength = $LEN;" + - metavariable-comparison: + metavariable: "$LEN" + comparison: "$LEN < 8" + - patterns: + - pattern: "$OPT.Password.RequiredUniqueChars = $LEN;" + - metavariable-comparison: + metavariable: "$LEN" + comparison: "$LEN < 1" + message: | + The application's `PasswordValidator.RequiredLength` property allows passwords + to be less than 8 characters. Consider requiring a length of at least 8 or more + characters to reduce the chance of passwords being brute forced. + + Example of setting the RequiredLength to 8 in ASP.NET Core Identity: + ``` + builder.Services.Configure(options => + { + // Default Password settings. + options.Password.RequireDigit = true; + options.Password.RequireLowercase = true; + options.Password.RequireNonAlphanumeric = true; + options.Password.RequireUppercase = true; + options.Password.RequiredLength = 8; + options.Password.RequiredUniqueChars = 1; + }); + ``` + + For more information on configuring ASP.NET Core Identity see: + https://learn.microsoft.com/en-us/aspnet/core/security/authentication/identity-configuration + severity: "WARNING" + metadata: + shortDescription: "Weak password requirements" + category: "security" + cwe: "CWE-521" + owasp: + - "A2:2017-Broken Authentication" + - "A07:2021-Identification and Authentication Failures" + security-severity: "Info" +- id: csharp_path_rule-PathTraversal + languages: + - "csharp" + mode: "taint" + pattern-sources: + - patterns: + - pattern-inside: | + public class $CLASS : Controller { + ... + } + - pattern: "$PARAM" + - pattern-either: + - patterns: + - metavariable-regex: + metavariable: "$HTTP_ANNO" + regex: "^(Http)" + - pattern-inside: | + [$HTTP_ANNO] + public string $METHOD(...,$PARAM,...){...} + - pattern-inside: | + public IActionResult $METHOD(...,$PARAM,...){...} + pattern-sanitizers: + - pattern-either: + - pattern: "(Microsoft.Extensions.FileProviders.PhysicalFileProvider $E).GetFileInfo(...)" + - pattern: "(System.Web.HttpServerUtility $E).MapPath(...)" + - pattern: "(System.Web.HttpServerUtilityBase $E).MapPath(...)" + - pattern: "(System.Web.HttpRequest $E).MapPath(...)" + pattern-sinks: + - pattern-either: + - pattern: "System.IO.Directory.Delete(...)" + - pattern: "System.IO.Directory.GetFiles(...)" + - pattern: "System.IO.Directory.Move(...)" + - pattern: "System.IO.File.AppendAllLines(...)" + - pattern: "System.IO.File.AppendAllLinesAsync(...)" + - pattern: "System.IO.File.AppendAllText(...)" + - pattern: "System.IO.File.AppendAllTextAsync(...)" + - pattern: "System.IO.File.AppendText(...)" + - pattern: "System.IO.File.Copy(...)" + - pattern: "System.IO.File.Create(...)" + - pattern: "System.IO.File.CreateText(...)" + - pattern: "System.IO.File.Delete(...)" + - pattern: "System.IO.File.Move(...)" + - pattern: "System.IO.File.Open(...)" + - pattern: "System.IO.File.OpenRead(...)" + - pattern: "System.IO.File.OpenText(...)" + - pattern: "System.IO.File.OpenWrite(...)" + - pattern: "System.IO.File.ReadAllBytes(...)" + - pattern: "System.IO.File.ReadAllBytesAsync(...)" + - pattern: "System.IO.File.ReadAllLines(...)" + - pattern: "System.IO.File.ReadAllLinesAsync(...)" + - pattern: "System.IO.File.ReadAllText(...)" + - pattern: "System.IO.File.ReadAllTextAsync(...)" + - pattern: "System.IO.File.ReadLines(...)" + - pattern: "System.IO.File.Replace(...)" + - pattern: "System.IO.File.SetAccessControl(...)" + - pattern: "System.IO.File.WriteAllBytes(...)" + - pattern: "System.IO.File.WriteAllBytesAsync(...)" + - pattern: "System.IO.File.WriteAllLines(...)" + - pattern: "System.IO.File.WriteAllLinesAsync(...)" + - pattern: "System.IO.File.WriteAllText(...)" + - pattern: "System.IO.File.WriteAllTextAsync(...)" + - pattern: "new System.IO.FileInfo(...)" + - pattern: "(System.IO.FileInfo $E).CopyTo(...)" + - pattern: "(System.IO.FileInfo $E).MoveTo(...)" + - pattern: "(System.IO.FileInfo $E).Replace(...)" + - pattern: "System.Reflection.Assembly.LoadFile(...)" + - pattern: "System.Reflection.Assembly.LoadFrom(...)" + - pattern: "System.Reflection.Assembly.ReflectionOnlyLoadFrom(...)" + - pattern: "System.Reflection.Assembly.UnsafeLoadFrom(...)" + - pattern: "System.AppDomain.AppendPrivatePath(...)" + - pattern: "System.Xml.XmlReader.Create(...)" + - pattern: "new System.IO.StreamReader.ctor(...)" + - pattern: "new System.IO.StreamWriter.ctor(...)" + - pattern: "new System.IO.FileStream.ctor(...)" + - pattern: "new System.Web.Mvc.FilePathResult(...)" + - pattern: "new Microsoft.AspNetCore.Mvc.PhysicalFileResult(...)" + - pattern: "(Microsoft.AspNetCore.Mvc.RazorPages.PageModel $E).PhysicalFile(...)" + - pattern: "(System.Web.UI.WebControls.FileUpload $E).SaveAs(...)" + - pattern: "(System.Web.HttpResponse $E).TransmitFile(...)" + - pattern: "(System.Web.HttpResponse $E).WriteFile(...)" + - pattern: "(System.Web.HttpResponseBase $E).TransmitFile(...)" + - pattern: "(System.Web.HttpResponseBase $E).WriteFile(...)" + - pattern: "(System.IO.Compression.ZipFileExtensions $E).CreateEntryFromFile(...)" + - pattern: "(System.IO.Compression.ZipFileExtensions $E).ExtractToFile(...)" + - pattern: "(System.IO.Compression.ZipFileExtensions $E).ExtractToDirectory(...)" + - pattern: "(System.Net.WebClient $E).DownloadFile(...)" + - pattern: "(System.Net.WebClient $E).DownloadFileAsync(...)" + - pattern: "(System.Net.WebClient $E).DownloadFileTaskAsync(...)" + message: | + The application dynamically constructs file or path information. If the path + information comes from user input, it could be abused to read sensitive files, + access other users data, or aid in exploitation to gain further system access. + + User input should never be used in constructing paths or files for interacting + with the filesystem. This includes filenames supplied by user uploads or downloads. + If possible consider hashing user input or replacing it with unique values and + use `System.IO.Path.GetFullPath` to resolve and validate the path information + prior to processing any file functionality. + + Example using `Path.GetFullPath` and not allowing direct user input: + ``` + // store user input alongside an ID we control + struct userData + { + public string userFilename; + public Guid id; + } + + class Program + { + public static void Main() + { + userData data = new userData(); + // user input, saved only as a reference + data.userFilename = "..\\test.txt"; + + // random id as the filename + data.id = Guid.NewGuid(); + + // restrict all file processing to this directory only + string basePath = "C:\\Restricted\\"; + + // resolve the full path, but only use our random generated id + string fullPath = Path.GetFullPath(basePath + data.id); + + // verify the path is contained within our basePath + if (!fullPath.StartsWith(basePath)) { + Console.WriteLine("Invalid path specified!"); + return; + } + // process / work with file + } + } + ``` + + For more information on path traversal issues see OWASP: + https://owasp.org/www-community/attacks/Path_Traversal + metadata: + shortDescription: "Improper limitation of a pathname to a restricted directory + ('Path Traversal')" + category: "security" + cwe: "CWE-22" + owasp: + - "A5:2017-Broken Access Control" + - "A01:2021-Broken Access Control" + security-severity: "Medium" + severity: "WARNING" +- id: csharp_validation_rule-InputValidation + languages: + - "csharp" + patterns: + - pattern: | + [ValidateInput(false)] + public $RET $FOO(...) + { + ... + } + message: | + By using the `[ValidateInput(false)]` attribute in a controller + class, the application will disable request validation for that + method. This disables ASP.NET from examining requests for injection + attacks such as Cross-Site-Scripting (XSS). + + If possible, re-enable validation by using `ValidateInput(true)`. + In some cases this may not be possible, in which case ensure how the + request data used is validated and this method does not + output user input directly into the view. + + For more information on protecting ASP.NET Core applications from XSS see: + https://learn.microsoft.com/en-us/aspnet/core/security/cross-site-scripting + + Example of enabling `ValidateInput` attribute: + ``` + class ControllerClass + { + [ValidateInput(true)] + public void SomeActionMethod() + { + } + } + ``` + + For more information on ASP.NET request validation see OWASP: + https://owasp.org/www-community/ASP-NET_Request_Validation + severity: "WARNING" + metadata: + shortDescription: "ASP.NET input validation disabled" + category: "security" + cwe: "CWE-554" + owasp: + - "A6:2017-Security Misconfiguration" + - "A05:2021-Security Misconfiguration" + security-severity: "Info" +- id: csharp_xss_rule-HtmlElementXss + mode: "taint" + pattern-sources: + - patterns: + - pattern: "$PARAM" + - pattern-inside: | + $RET $METHOD(...,$PARAM,...){...} + - pattern: "Request.Cookies[...]" + - pattern: "Request.Cookies.Get(...)" + - pattern: "Request.Form[...]" + - pattern: "Request.Form.Get(...)" + - pattern: "Request.Headers[...]" + - pattern: "Request.Headers.Get(...)" + - pattern: "Request.QueryString[...]" + - pattern: "Request.QueryString.Get(...)" + - pattern: "Request.Params[...]" + - pattern: "Request.RawUrl" + - pattern: "Request.Url" + - pattern: "Request.Path" + - pattern: "Request.Body" + - pattern: "$CTX.Request.Cookies[...]" + - pattern: "$CTX.Request.Cookies.Get(...)" + - pattern: "$CTX.Request.Form[...]" + - pattern: "$CTX.Request.Form.Get(...)" + - pattern: "$CTX.Request.Headers[...]" + - pattern: "$CTX.Request.Headers.Get(...)" + - pattern: "$CTX.Request.QueryString[...]" + - pattern: "$CTX.Request.QueryString.Get(...)" + - pattern: "$CTX.Request.Body" + pattern-sanitizers: + - patterns: + - metavariable-regex: + metavariable: "$FUNC" + regex: "(SerializeObject|HtmlAttributeEncode|HtmlEncode|HtmlFormUrlEncode|UrlEncode|UrlPathEncode|XmlAttributeEncode|XmlEncode|Encode)" + - pattern: "$CLASS.$FUNC(...)" + pattern-sinks: + - pattern: "(System.Web.Mvc.HtmlHelper $E).Raw(...)" + - pattern: "(Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper $E).Raw(...)" + - pattern: "Response.Write(...)" + - pattern: "(System.Web.UI.HtmlTextWriter $E).AddAttribute(...)" + - pattern: "(System.Web.UI.HtmlTextWriter $E).AddStyleAttribute(...)" + - pattern: "(System.Web.UI.HtmlTextWriter $E).RenderBeginTag(...)" + - pattern: "(System.Web.UI.HtmlTextWriter $E).Write(...)" + - pattern: "(System.Web.UI.HtmlTextWriter $E).WriteAttribute(...)" + - pattern: "(System.Web.UI.HtmlTextWriter $E).WriteBeginTag(...)" + - pattern: "(System.Web.UI.HtmlTextWriter $E).WriteEndTag(...)" + - pattern: "(System.Web.UI.HtmlTextWriter $E).WriteFullBeginTag(...)" + - pattern: "(System.Web.UI.HtmlTextWriter $E).WriteStyleAttribute(...)" + languages: + - "csharp" + message: | + Cross Site Scripting (XSS) is an attack which exploits a web application or system to treat + user input + as markup or script code. It is important to encode the data depending on the specific context + it + is used in. There are at least six context types: + + - Inside HTML tags `
context 1
` + - Inside attributes: `
` + - Inside event attributes `` + - Inside script blocks: `` + - Unsafe element HTML assignment: `element.innerHTML = "context 5"` + - Inside URLs: `
link` + User input that is displayed within the application must be encoded, sanitized or validated + to ensure it cannot be treated as HTML or executed as Javascript code. Care must also be + taken + to not mix server-side templating with client-side templating, as the server-side templating + will + not encode things like {{ 7*7 }} which may execute client-side templating features. + + It is _NOT_ advised to encode user input prior to inserting into a data store. The data will + need to be + encoded depending on context of where it is output. It is much safer to force the displaying + system to + handle the encoding and not attempt to guess how it should be encoded. + + Consider using built-in framework capabilities for automatically encoding user input. + Depending + on output context, consider using the following `System.Text.Encodings.Web` encoders: + + - [HtmlEncoder](https://learn.microsoft.com/en-us/dotnet/api/system.text.encodings.web.htmlencoder) + - [JavaScriptEncoder](https://learn.microsoft.com/en-us/dotnet/api/system.text.encodings.web.javascriptencoder) + - [UrlEncoder](https://learn.microsoft.com/en-us/dotnet/api/system.text.encodings.web.urlencoder) + + For more information on protecting ASP.NET Core applications from XSS see: + https://learn.microsoft.com/en-us/aspnet/core/security/cross-site-scripting#accessing-encoders-in-code + metadata: + shortDescription: "Improper neutralization of input during web page generation + ('Cross-site Scripting')" + category: "security" + cwe: "CWE-79" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "Medium" + severity: "WARNING" +- id: csharp_xss_rule-ScriptXss + mode: "taint" + pattern-sources: + - patterns: + - pattern: "$PARAM" + - pattern-inside: | + $RET $METHOD(...,$PARAM,...){...} + - pattern: "Request.Cookies[...]" + - pattern: "Request.Cookies.Get(...)" + - pattern: "Request.Form[...]" + - pattern: "Request.Form.Get(...)" + - pattern: "Request.Headers[...]" + - pattern: "Request.Headers.Get(...)" + - pattern: "Request.QueryString[...]" + - pattern: "Request.QueryString.Get(...)" + - pattern: "Request.Params[...]" + - pattern: "Request.RawUrl" + - pattern: "Request.Url" + - pattern: "Request.Path" + - pattern: "Request.Body" + - pattern: "$CTX.Request.Cookies[...]" + - pattern: "$CTX.Request.Cookies.Get(...)" + - pattern: "$CTX.Request.Form[...]" + - pattern: "$CTX.Request.Form.Get(...)" + - pattern: "$CTX.Request.Headers[...]" + - pattern: "$CTX.Request.Headers.Get(...)" + - pattern: "$CTX.Request.QueryString[...]" + - pattern: "$CTX.Request.QueryString.Get(...)" + - pattern: "$CTX.Request.Body" + - pattern: "$ELE.Text" + pattern-sanitizers: + - patterns: + - metavariable-regex: + metavariable: "$FUNC" + regex: "(SerializeObject|HtmlAttributeEncode|HtmlEncode|HtmlFormUrlEncode|UrlEncode|UrlPathEncode|XmlAttributeEncode|XmlEncode|Encode)" + - pattern: "$CLASS.$FUNC(...)" + pattern-propagators: + - pattern: "(StringBuilder $OUT).Append($IN)" + from: "$IN" + to: "$OUT" + pattern-sinks: + - pattern: "$SCRIPTMANAGER.RegisterStartupScript(...)" + - pattern: "$SCRIPTMANAGER.RegisterClientScriptBlock(...)" + - pattern: "System.Web.UI.RegisterStartupScript(...)" + - pattern: "System.Web.UI.RegisterClientScriptBlock(...)" + languages: + - "csharp" + message: | + Cross Site Scripting (XSS) is an attack which exploits a web application or system to treat + user input + as markup or script code. It is important to encode the data depending on the specific context + it + is used in. + + User input that is used within the application scripts must be encoded, sanitized or validated + to ensure it cannot change the behavior of the Javascript code. + + It is _NOT_ advised to encode user input prior to inserting into a data store. The data will + need to be + encoded depending on context of where it is output. It is much safer to force the displaying + system to + handle the encoding and not attempt to guess how it should be encoded. + + Consider using built-in framework capabilities for automatically encoding user input. + Depending + on output context, consider using the following `System.Text.Encodings.Web` encoders: + + - [HtmlEncoder](https://learn.microsoft.com/en-us/dotnet/api/system.text.encodings.web.htmlencoder) + - [JavaScriptEncoder](https://learn.microsoft.com/en-us/dotnet/api/system.text.encodings.web.javascriptencoder) + - [UrlEncoder](https://learn.microsoft.com/en-us/dotnet/api/system.text.encodings.web.urlencoder) + + For more information on protecting ASP.NET Core applications from XSS see: + https://learn.microsoft.com/en-us/aspnet/core/security/cross-site-scripting#accessing-encoders-in-code + metadata: + shortDescription: "Improper neutralization of input during web page generation + ('Cross-site Scripting')" + category: "security" + cwe: "CWE-79" + security-severity: "MEDIUM" + severity: "WARNING" +- id: go_blocklist_rule-blocklist-des + languages: + - "go" + patterns: + - pattern: | + import "crypto/des" + message: | + The DES algorithm has not been recommended for over 15 years and was withdrawn from NIST (FIPS + 46-3) in 2005. It is recommended that an algorithm that provides message integrity be used + instead. Consider using `XChaCha20Poly1305` or `AES-256-GCM`. + + For older applications, `AES-256-GCM` is recommended, however it has many drawbacks: + - Slower than `XChaCha20Poly1305` + - Smaller nonce value size compared to `XChaCha20Poly1305` + - Catastrophic failure if nonce values are re-used + + Example using + [XChaCha20Poly1305](https://pkg.go.dev/golang.org/x/crypto/chacha20poly1305#NewX): + ``` + key := make([]byte, chacha20poly1305.KeySize) + if _, err := io.ReadFull(rand.Reader, key); err != nil { + log.Fatal(err) + } + + // NewX is a variant that uses longer nonce values for better security + aead, err := chacha20poly1305.NewX(key) + if err != nil { + log.Fatal(err) + } + + var encrypted = []byte{} + var nonce = []byte{} + + // Encryption routine + { + msg := []byte("Some secret message") + nonce = make([]byte, aead.NonceSize()) + if _, err := io.ReadFull(rand.Reader, nonce); err != nil { + log.Fatal("failed to generate nonce") + } + + encrypted = aead.Seal(nil, nonce, msg, nil) + } + + // Decryption routine + { + if len(encrypted) < aead.NonceSize() { + log.Fatal("incorrect ciphertext length") + } + + msg, err := aead.Open(nil, nonce, encrypted, nil) + if err != nil { + log.Fatal(err) + } + fmt.Printf("Decrypted: %s\n", msg) + } + ``` + + Example using [AES-256-GCM](https://pkg.go.dev/crypto/cipher#NewGCM): + ``` + // 32 byte keys will configure AES-256 + key := make([]byte, 32) + if _, err := io.ReadFull(rand.Reader, key); err != nil { + log.Fatal(err) + } + + blockCipher, err := aes.NewCipher(key) + if err != nil { + log.Fatal(err) + } + + aead, err := cipher.NewGCM(blockCipher) + if err != nil { + log.Fatal(err) + } + + var encrypted = []byte{} + var nonce = []byte{} + // Encryption routine + { + msg := []byte("Some secret message") + // note that the key must be rotated every 2^32 random nonces used otherwise + // cipher text could be repeated + nonce = make([]byte, 12) + if _, err := io.ReadFull(rand.Reader, nonce); err != nil { + log.Fatal(err) + } + encrypted = aead.Seal(nil, nonce, msg, nil) + } + + // Decryption routine + { + msg, err := aead.Open(nil, nonce, encrypted, nil) + if err != nil { + log.Fatal(err) + } + fmt.Printf("Decrypted: %s\n", msg) + } + ``` + metadata: + shortDescription: "Use of a broken or risky cryptographic algorithm" + cwe: "CWE-327" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + security-severity: "Medium" + category: "security" + severity: "WARNING" +- id: go_blocklist_rule-blocklist-md5 + languages: + - "go" + patterns: + - pattern: | + import "crypto/md5" + message: | + The MD5 message-digest algorithm has been cryptographically broken and is unsuitable for + further use. The MD5 hash algorithm has been found to be vulnerable to producing collisions. + This means that two different values, when hashed, can lead to the same hash value. It is + recommended that the SHA-3 or BLAKE2 family of algorithms be used for non-password based + cryptographic hashes instead. For password based cryptographic hashes, consider using the + bcrypt or Argon2id family of cryptographic hashes. + + Hashing values using [BLAKE2](https://pkg.go.dev/golang.org/x/crypto/blake2b): + ``` + fileContents := []byte("some file contents to create hash for") + blake2bHasher, err := blake2b.New512(nil) + if err != nil { + log.Fatal(err) + } + hashedValue := blake2bHasher.Sum(fileContents) + fmt.Printf("%s\n", hex.EncodeToString(hashedValue)) + ``` + + Hashing and securely comparing passwords using + [Argon2id](https://pkg.go.dev/golang.org/x/crypto/argon2#hdr-Argon2id): + ``` + type argonParameters struct { + variant string + version int + memory uint32 + iterations uint32 + parallelism uint8 + saltLength uint32 + keyLength uint32 + } + + func (a argonParameters) StringFormat(salt, derivedKey []byte) string { + encodedSalt := base64.RawStdEncoding.EncodeToString(salt) + encodedKey := base64.RawStdEncoding.EncodeToString(derivedKey) + + return fmt.Sprintf("$argon2id$v=%d$m=%d,t=%d,p=%d$%s$%s", + argon2.Version, + a.memory, + a.iterations, + a.parallelism, + encodedSalt, + encodedKey, + ) + } + + func main() { + // Initialize Argon2id parameters + p := argonParameters{ + memory: 64 * 1024, + iterations: 3, + parallelism: 2, + saltLength: 16, + keyLength: 32, + } + + // Generate random salt (to be stored alongside derived hash key) + salt := make([]byte, p.saltLength) + if _, err := io.ReadFull(rand.Reader, salt); err != nil { + log.Fatal(err) + } + + usersPassword := []byte("User's Very S3cur3P4ss@rd@#$%") + + var derivedKey []byte + // Create key hash derived from user's password + { + derivedKey = argon2.IDKey(usersPassword, salt, p.iterations, p.memory, p.parallelism, + p.keyLength) + // store p.StringFormat(...) result in a data store... + fmt.Printf("%s\n", p.StringFormat(salt, derivedKey)) + } + + // Verify a user's password against key + { + keyToCompare := argon2.IDKey(usersPassword, salt, p.iterations, p.memory, p.parallelism, + p.keyLength) + + // Use subtle.ConstantTimeCompare(..., ...) to ensure no side channel leaks used in timing + attacks + if subtle.ConstantTimeCompare(derivedKey, keyToCompare) == 1 { + fmt.Printf("Passwords match\n") + } else { + fmt.Printf("Passwords do not match\n") + } + } + } + ``` + + For more information on password storage see OWASP's guide: + https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html + metadata: + shortDescription: "Use of a broken or risky cryptographic algorithm" + cwe: "CWE-327" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + security-severity: "Medium" + category: "security" + severity: "WARNING" +- id: go_blocklist_rule-blocklist-rc4 + languages: + - "go" + patterns: + - pattern: | + import "crypto/rc4" + message: | + The RC4 stream-cipher has been cryptographically broken and is unsuitable + for use in production. It is recommended that ChaCha20 or Advanced Encryption + Standard (AES) be used instead. Consider using `XChaCha20Poly1305` or `AES-256-GCM`. + + For older applications, `AES-256-GCM` is recommended, however it has many drawbacks: + - Slower than `XChaCha20Poly1305` + - Smaller nonce value size compared to `XChaCha20Poly1305` + - Catastrophic failure if nonce values are re-used + + Example using + [XChaCha20Poly1305](https://pkg.go.dev/golang.org/x/crypto/chacha20poly1305#NewX): + ``` + key := make([]byte, chacha20poly1305.KeySize) + if _, err := io.ReadFull(rand.Reader, key); err != nil { + log.Fatal(err) + } + + // NewX is a variant that uses longer nonce values for better security + aead, err := chacha20poly1305.NewX(key) + if err != nil { + log.Fatal(err) + } + + var encrypted = []byte{} + var nonce = []byte{} + + // Encryption routine + { + msg := []byte("Some secret message") + nonce = make([]byte, aead.NonceSize()) + if _, err := io.ReadFull(rand.Reader, nonce); err != nil { + log.Fatal("failed to generate nonce") + } + + encrypted = aead.Seal(nil, nonce, msg, nil) + } + + // Decryption routine + { + if len(encrypted) < aead.NonceSize() { + log.Fatal("incorrect ciphertext length") + } + + msg, err := aead.Open(nil, nonce, encrypted, nil) + if err != nil { + log.Fatal(err) + } + fmt.Printf("Decrypted: %s\n", msg) + } + ``` + + Example using [AES-256-GCM](https://pkg.go.dev/crypto/cipher#NewGCM): + ``` + // 32 byte keys will configure AES-256 + key := make([]byte, 32) + if _, err := io.ReadFull(rand.Reader, key); err != nil { + log.Fatal(err) + } + + blockCipher, err := aes.NewCipher(key) + if err != nil { + log.Fatal(err) + } + + aead, err := cipher.NewGCM(blockCipher) + if err != nil { + log.Fatal(err) + } + + var encrypted = []byte{} + var nonce = []byte{} + // Encryption routine + { + msg := []byte("Some secret message") + // note that the key must be rotated every 2^32 random nonces used otherwise + // cipher text could be repeated + nonce = make([]byte, 12) + if _, err := io.ReadFull(rand.Reader, nonce); err != nil { + log.Fatal(err) + } + encrypted = aead.Seal(nil, nonce, msg, nil) + } + + // Decryption routine + { + msg, err := aead.Open(nil, nonce, encrypted, nil) + if err != nil { + log.Fatal(err) + } + fmt.Printf("Decrypted: %s\n", msg) + } + ``` + metadata: + shortDescription: "Use of a broken or risky cryptographic algorithm" + cwe: "CWE-327" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + security-severity: "Medium" + category: "security" + severity: "WARNING" +- id: go_blocklist_rule-blocklist-sha1 + languages: + - "go" + patterns: + - pattern: | + import "crypto/sha1" + message: | + The SHA-1 message-digest algorithm has been cryptographically broken and + is unsuitable for further use. It is + recommended that the SHA-3, or BLAKE2 family of algorithms be used for non-password based + cryptographic hashes instead. For password based cryptographic hashes, consider using the + bcrypt or Argon2id family of cryptographic hashes. + + Hashing values using [BLAKE2](https://pkg.go.dev/golang.org/x/crypto/blake2b): + ``` + fileContents := []byte("some file contents to create hash for") + blake2bHasher, err := blake2b.New512(nil) + if err != nil { + log.Fatal(err) + } + hashedValue := blake2bHasher.Sum(fileContents) + fmt.Printf("%s\n", hex.EncodeToString(hashedValue)) + ``` + + Hashing and securely comparing passwords using + [Argon2id](https://pkg.go.dev/golang.org/x/crypto/argon2#hdr-Argon2id): + ``` + type argonParameters struct { + variant string + version int + memory uint32 + iterations uint32 + parallelism uint8 + saltLength uint32 + keyLength uint32 + } + + func (a argonParameters) StringFormat(salt, derivedKey []byte) string { + encodedSalt := base64.RawStdEncoding.EncodeToString(salt) + encodedKey := base64.RawStdEncoding.EncodeToString(derivedKey) + + return fmt.Sprintf("$argon2id$v=%d$m=%d,t=%d,p=%d$%s$%s", + argon2.Version, + a.memory, + a.iterations, + a.parallelism, + encodedSalt, + encodedKey, + ) + } + + func main() { + // Initialize Argon2id parameters + p := argonParameters{ + memory: 64 * 1024, + iterations: 3, + parallelism: 2, + saltLength: 16, + keyLength: 32, + } + + // Generate random salt (to be stored alongside derived hash key) + salt := make([]byte, p.saltLength) + if _, err := io.ReadFull(rand.Reader, salt); err != nil { + log.Fatal(err) + } + + usersPassword := []byte("User's Very S3cur3P4ss@rd@#$%") + + var derivedKey []byte + // Create key hash derived from user's password + { + derivedKey = argon2.IDKey(usersPassword, salt, p.iterations, p.memory, p.parallelism, + p.keyLength) + // store p.StringFormat(...) result in a data store... + fmt.Printf("%s\n", p.StringFormat(salt, derivedKey)) + } + + // Verify a user's password against key + { + keyToCompare := argon2.IDKey(usersPassword, salt, p.iterations, p.memory, p.parallelism, + p.keyLength) + + // Use subtle.ConstantTimeCompare(..., ...) to ensure no side channel leaks used in timing + attacks + if subtle.ConstantTimeCompare(derivedKey, keyToCompare) == 1 { + fmt.Printf("Passwords match\n") + } else { + fmt.Printf("Passwords do not match\n") + } + } + } + ``` + + For more information on password storage see OWASP's guide: + https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html + metadata: + shortDescription: "Use of a broken or risky cryptographic algorithm" + cwe: "CWE-327" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + security-severity: "Medium" + category: "security" + severity: "WARNING" +- id: go_crypto_rule-badtlssettings + languages: + - "go" + patterns: + - pattern-either: + - pattern: | + tls.Config{..., CipherSuites: []$SLICE{..., $CIPHERS, ...}, ...} + - pattern: | + tls.CipherSuite{..., ID: $CIPHERS, ...} + - metavariable-regex: + metavariable: "$CIPHERS" + regex: "((?!tls.TLS_AES_128_GCM_SHA256)|(?!tls.TLS_AES_256_GCM_SHA384)|(?!tls.TLS_CHACHA20_POLY1305_SHA256)| + (?!tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256)|(?!tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256)| + (?!tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384)|(?!tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384)| + (?!tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305)|(?!tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256)| + (?!tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305)|(?!tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256)| + (?!tls.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256)|(?!tls.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384))" + message: | + Usage of a cryptographically insecure cipher suite has been detected. It is recommended that + alternative ciphers be used instead. It is strongly recommended that all TLS connections + use TLS 1.3 as Go will automatically choose the most secure cipher when negotiating the + TLS handshake with client or servers. TLS 1.3 cipher suites are configured to require Perfect + Forward Secrecy (PFS). + PFS is an important property as it will ensure that past encrypted transmissions could not be + decrypted + if the TLS certificate was compromised. + + Example using TLS 1.3 for a Go server: + ``` + cert, err := tls.LoadX509KeyPair("server.crt", "server.key") + if err != nil { + log.Fatal(err) + } + + cfg := &tls.Config{Certificates: []tls.Certificate{cert}, MinVersion: tls.VersionTLS13} + srv := &http.Server{ + Addr: ":8999", + TLSConfig: cfg, + ReadTimeout: time.Minute, + WriteTimeout: time.Minute, + } + log.Fatal(srv.ListenAndServeTLS("", "")) + ``` + + If TLS 1.0-1.2 must be used, then the following list of ciphers should be chosen as they + support + Perfect Forward Secrecy (PFS): + + - TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + - TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + - TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305 + - TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305 + + + Example `tls.Config` using the recommended cipher suites: + ``` + cfg := &tls.Config{ + MinVersion: tls.VersionTLS12, + CipherSuites: []uint16{ + tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, + tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, + }, + } + ``` + + For more information on cipher suites in Go see: https://go.dev/blog/tls-cipher-suites + metadata: + shortDescription: "Use of a broken or risky cryptographic algorithm" + cwe: "CWE-327" + category: "security" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + security-severity: "Medium" + severity: "WARNING" +- id: go_crypto_rule-insecure-ignore-host-key + languages: + - "go" + patterns: + - pattern: "ssh.InsecureIgnoreHostKey(...)" + message: | + The application was found to ignore host keys. Host keys are important as + they provide assurance that the client can prove that the host is trusted. + By ignoring these host keys, it is impossible for the client to validate the + connection is to a trusted host. + + For the `ssh.ClientConfig` `HostKeyCallback` property, consider using the + [knownhosts](https://pkg.go.dev/golang.org/x/crypto/ssh/knownhosts) package that + parses OpenSSH's `known_hosts` key database. + + Example configuration connecting to a known, trusted host: + ``` + knownHostCallback, err := knownhosts.New("/home/user/.ssh/known_hosts") + if err != nil { + log.Fatal(err) + } + + // Create client config using the knownHost callback function + config := &ssh.ClientConfig{ + ... + HostKeyCallback: knownHostCallback, + } + + // Connect to ssh server + conn, err := ssh.Dial("tcp", "localhost:22", config) + if err != nil { + log.Fatal("unable to connect: ", err) + } + defer conn.Close() + ``` + metadata: + shortDescription: "Key exchange without entity authentication" + cwe: "CWE-322" + owasp: + - "A2:2017-Broken Authentication" + - "A07:2021-Identification and Authentication Failures" + security-severity: "Medium" + category: "security" + severity: "WARNING" +- id: go_crypto_rule-tlsversion + languages: + - "go" + pattern-either: + - patterns: + - pattern-either: + - patterns: + - pattern-inside: | + tls.Config{...} + - pattern: | + MinVersion: $VAL + - patterns: + - pattern-inside: | + $VAR = uint16($VAL) + ... + - pattern-inside: | + tls.Config{...} + - pattern: | + MinVersion: $VAR + - metavariable-pattern: + metavariable: $VAL + pattern-either: + - pattern: "tls.VersionTLS11" + - pattern: "tls.VersionTLS10" + - patterns: + - pattern-inside: | + tls.Config{...} + - pattern: | + MaxVersion: $ANYVAL + - pattern-not-inside: | + tls.Config{..., MinVersion: ..., ...} + message: | + TLS versions 1.1 and 1.0 were deprecated by the IETF in June 2018 due to + a number of attacks against the vulnerable versions. Use of a deprecated + TLS version may result in the unauthorized retrieval of sensitive + information. It is strongly recommended that all TLS connections + use TLS 1.3 as Go will automatically choose the most secure cipher when + negotiating the TLS handshake with client or servers. TLS 1.3 cipher suites + are configured to require Perfect Forward Secrecy (PFS). PFS is an important + property as it will ensure that past encrypted transmissions could not be + decrypted if the TLS certificate was compromised. + + Example using TLS 1.3 for a Go server: + ``` + cert, err := tls.LoadX509KeyPair("server.crt", "server.key") + if err != nil { + log.Fatal(err) + } + + cfg := &tls.Config{Certificates: []tls.Certificate{cert}, + MinVersion: tls.VersionTLS13} + + srv := &http.Server{ + Addr: ":8999", + TLSConfig: cfg, + ReadTimeout: time.Minute, + WriteTimeout: time.Minute, + } + log.Fatal(srv.ListenAndServeTLS("cert.pem", "key.pem")) + ``` + metadata: + shortDescription: "Use of deprecated TLS version" + cwe: "CWE-310" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + security-severity: "Medium" + category: "security" + severity: "WARNING" +- id: go_crypto_rule-weakkeystrength + languages: + - "go" + patterns: + - pattern-either: + - pattern: | + rsa.GenerateKey(..., $ARG) + - metavariable-comparison: + metavariable: "$ARG" + comparison: "$ARG < 2048" + message: | + The application is generating an RSA key that is less than the recommended 2048 bits. + The National Institute of Standards and Technology (NIST) deprecated signing Digital + Certificates that contained RSA Public Keys of 1024 bits in December 2010. While + 1024-bit RSA keys have not been factored yet, advances in compute may make it possible + in the near future. + + To generate an RSA key of 2048 pass the number of bits as the second parameter to + the `rsa.GenerateKey` function: + ``` + import ( + "crypto/rand" + "crypto/rsa" + ) + + func generate() { + key, err := rsa.GenerateKey(rand.Reader, 2048) + if err != nil { + log.Fatal(err) + } + } + ``` + metadata: + shortDescription: "Inadequate encryption strength" + cwe: "CWE-326" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + security-severity: "Medium" + category: "security" + severity: "WARNING" +- id: go_crypto_rule-weakrandsource + languages: + - "go" + patterns: + - patterns: + - pattern-inside: | + import $IMPORT "math/rand" + ... + - pattern-not-inside: | + import "crypto/rand" + - pattern-either: + - pattern: "$IMPORT.$METHOD(...)" + - pattern: "rand.$METHOD(...)" + - metavariable-regex: + metavariable: "$METHOD" + regex: "(Float32|Float64|Int31|Int31n|Int63|Int63n|NormalFloat64|Uint32|Uint64)" + message: | + Go's `math/rand` is not meant for use in generating random numbers for any cryptographic or + security sensitive context. This includes generating random numbers that could be used in + user specific identifiers or where the random number that is generated is considered to + be secret. + + Replace all imports of `math/rand` with `crypto/rand`. + metadata: + shortDescription: "Use of cryptographically weak Pseudo-Random Number Generator + (PRNG)" + cwe: "CWE-338" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + security-severity: "Medium" + category: "security" + severity: "WARNING" +- id: go_file-permissions_rule-fileperm + languages: + - "go" + patterns: + - pattern-either: + - pattern: "os.Chmod(...,$MASK)" + - pattern: "os.OpenFile(...,$MASK)" + - pattern: "os.WriteFile(...,$MASK)" + - metavariable-comparison: + metavariable: "$MASK" + comparison: "$MASK > 0o640" + base: 8 + message: | + The application was found setting file permissions to overly permissive values. Consider + using the following values if the application user is the only process to access + the file: + + - 0400 - read only access to the file + - 0200 - write only access to the file + - 0600 - read/write access to the file + + Example creating a file with read/write permissions for the application user: + ``` + f, err := os.OpenFile("file.txt", os.O_CREATE, 0600) + if err != nil { + log.Fatal(err) + } + defer f.Close() + // continue to work with file here + ``` + + For all other values please see: + https://en.wikipedia.org/wiki/File-system_permissions#Numeric_notation + metadata: + shortDescription: "Incorrect permission assignment for critical resource" + cwe: "CWE-732" + owasp: + - "A5:2017-Broken Access Control" + - "A01:2021-Broken Access Control" + security-severity: "Medium" + category: "security" + severity: "WARNING" +- id: go_file-permissions_rule-mkdir + languages: + - "go" + patterns: + - pattern-either: + - pattern: "os.Mkdir(...,$MASK)" + - pattern: "os.MkdirAll(...,$MASK)" + - metavariable-comparison: + metavariable: "$MASK" + comparison: "$MASK > 0o750" + base: 8 + message: | + The application was found setting directory permissions to overly permissive values. Consider + using the following values if the application user is the only process to access + files in the directory specified: + - 0700 - read/write access to the files in the directory + + Another common value is `0750` which allows the application user read/write access and group + users to read the files contained in the directory. + + Example creating a directory with read/write permissions for only the application user: + ``` + err := os.Mkdir("directory", 0700) + if err != nil { + log.Fatal(err) + } + ``` + + For all other values please see: + https://en.wikipedia.org/wiki/File-system_permissions#Numeric_notation + metadata: + shortDescription: "Incorrect permission assignment for critical resource" + cwe: "CWE-732" + owasp: + - "A5:2017-Broken Access Control" + - "A01:2021-Broken Access Control" + security-severity: "Medium" + category: "security" + severity: "WARNING" +- id: go_filesystem_rule-decompression-bomb + languages: + - "go" + mode: "taint" + pattern-sources: + - pattern: "gzip.NewReader(...)" + - pattern: "zlib.NewReader(...)" + - pattern: "bzip2.NewReader(...)" + - pattern: "flate.NewReader(...)" + - pattern: "lzw.NewReader(...)" + - pattern: "tar.NewReader(...)" + - pattern: "zip.NewReader(...)" + - pattern: "zlib.NewReaderDict(...)" + - pattern: "flate.NewReaderDict(...)" + - pattern: "zip.OpenReader(...)" + pattern-sanitizers: + - patterns: + - pattern: "io.LimitReader($TAINTED, ...)" + - focus-metavariable: "$TAINTED" + pattern-sinks: + - patterns: + - pattern: "io.Copy($DST, $TAINTED)" + - focus-metavariable: "$TAINTED" + - patterns: + - pattern: "io.CopyBuffer($DST, $TAINTED, $BUF)" + - focus-metavariable: "$TAINTED" + message: | + Directly decompressing files or buffers may lead to a potential Denial of Service (DoS) + due to a decompression bomb. Decompression bombs are maliciously compressed files + or data that decompresses to extremely large sizes. This can cause the process to run + out of memory, or the disk to fill up. + + To protect against decompression bombs, an + [io.LimitReader(...)](https://pkg.go.dev/io#LimitReader) + should be used to limit how much can be read during the decompression routine. + + Example using `io.LimitReader` to protect against a decompression bomb: + ``` + f, err := os.Open("some.gz") + if err != nil { + log.Fatal(err) + } + + r, err := gzip.NewReader(f) + if err != nil { + log.Fatal(err) + } + + const oneMegabyte = 1024 * 1024 + limitedReader := io.LimitReader(r, oneMegabyte) + + // use limitedReader to stop copying after 1 MB + if _, err := io.Copy(os.Stdout, limitedReader); err != nil { + log.Fatal(err) + } + ``` + metadata: + shortDescription: "Improper handling of highly compressed data" + cwe: "CWE-409" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "Medium" + category: "security" + severity: "WARNING" +- id: go_filesystem_rule-fileread + languages: + - "go" + mode: "taint" + pattern-sources: + - pattern: "os.Getenv(...)" + - pattern: "fmt.Sprintf(...)" + - pattern: "filepath.Join(...)" + - pattern: "path.Join(...)" + - patterns: + - pattern-either: + - pattern: "... + $TAINTED" + - pattern: "... + $TAINTED + ..." + - pattern: "$TAINTED + ..." + - pattern-not: "\"...\" + $TAINTED" + - pattern-not: "\"...\" + $TAINTED + \"...\"" + - pattern-not: "$TAINTED + \"...\"" + - pattern-not: "fmt.Sprintf(\"...\", \"...\")" + - patterns: + - pattern-either: + - pattern: | + ($REQUEST : *http.Request).$SOURCE_METHOD + - pattern: | + ($REQUEST : http.Request).$SOURCE_METHOD + - metavariable-regex: + metavariable: "$SOURCE_METHOD" + regex: "^(BasicAuth|Body|Cookie|Cookies|Form|FormValue|GetBody|Host|MultipartReader|ParseForm|ParseMultipartForm|PostForm|PostFormValue|Referer|RequestURI|Trailer|TransferEncoding|UserAgent|URL)$" + pattern-sanitizers: + - patterns: + - pattern-either: + - pattern: | + $CLEAN := $PKG.Clean(...) + ... + if !strings.HasPrefix($CLEAN, "...") {...} + - pattern: | + $CLEAN := $PKG.Clean(...) + ... + if strings.HasPrefix($CLEAN, "...") {...} + - pattern: | + $CLEAN := $PKG.Clean(...) + ... + if strings.HasPrefix($CLEAN, "...") == false {...} + - metavariable-regex: + metavariable: "$PKG" + regex: "^((file)?path)$" + pattern-sinks: + - pattern: "os.OpenFile(...)" + - pattern: "os.Open(...)" + - pattern: "os.ReadFile(...)" + - pattern: "ioutil.ReadFile(...)" + message: | + The application dynamically constructs file or path information. If the path + information comes from user input, it could be abused to read sensitive files, + access other users data or aid in exploitation to gain further system access. + + User input should never be used in constructing paths or files for interacting + with the filesystem. This includes filenames supplied by user uploads or downloads. + If possible, consider hashing user input or replacing it with unique values. + Additionally, use `filepath.Base` to only use the filename and not path information. + Always validate the full path prior to opening or writing to any file. + + Example using `filepath.Base`, generating a unique filename without using + user input to construct filepath information: + ``` + type userData struct { + id string + userFilename string + } + + func newUserData(userFilename string) userData { + return userData{ + id: randomFileID(), // random id as the filename + userFilename: userFilename, + } + } + + // randomFileID generates a random id, to be used as a filename + func randomFileID() string { + id := make([]byte, 16) + if _, err := io.ReadFull(rand.Reader, id); err != nil { + log.Fatal(err) + } + return hex.EncodeToString(id) + } + + func main() { + + // user input, saved only as a reference + data := newUserData("../../possibly/malicious") + + // restrict all file access to this path + const basePath = "/tmp/" + + // resolve the full path, but only use our random generated id + resolvedPath, err := filepath.Join(basePath, filepath.Base(data.id)) + if err != nil { + log.Fatal(err) + } + + // verify the path is prefixed with our basePath + if !strings.HasPrefix(resolvedPath, basePath) { + log.Fatal("path does not start with basePath") + } + // process / work with file + } + ``` + + For more information on path traversal issues see OWASP: + https://owasp.org/www-community/attacks/Path_Traversal + metadata: + shortDescription: "Improper limitation of a pathname to a restricted directory + ('Path Traversal')" + cwe: "CWE-22" + owasp: + - "A5:2017-Broken Access Control" + - "A01:2021-Broken Access Control" + security-severity: "Medium" + category: "security" + severity: "WARNING" +- id: go_filesystem_rule-httprootdir + languages: + - "go" + patterns: + - pattern-either: + - pattern: | + import $NET "net/http" + ... + $NET.Dir("/") + - pattern: | + import "net/http" + ... + http.Dir("/") + message: | + The application is potentially exposing the entire filesystem by mounting the root + directory `/` to an HTTP handler function. Anyone who is able to access this HTTP + server may be able to access any file that the HTTP server has access to. + + Restrict the `http.Dir` path to only a specific folder instead of the entire + filesystem. + + Example server only allowing directory listing on a public directory: + ``` + const path = "/var/www/html/public" + fs := http.FileServer(http.Dir(path)) + log.Fatal(http.ListenAndServe(":9000", fs)) + ``` + metadata: + shortDescription: "Files or directories accessible to external parties" + cwe: "CWE-552" + owasp: + - "A5:2017-Broken Access Control" + - "A01:2021-Broken Access Control" + security-severity: "Medium" + category: "security" + severity: "WARNING" +- id: go_filesystem_rule-poorwritepermissions + languages: + - "go" + patterns: + - pattern-either: + - pattern: | + ioutil.WriteFile(..., ..., $ARG) + - metavariable-comparison: + metavariable: "$ARG" + comparison: "$ARG > 0o600" + base: 8 + message: | + The application was found setting file permissions to overly permissive values. Consider + using the following values if the application user is the only process to access + the file: + + - 0400 - read only access to the file + - 0200 - write only access to the file + - 0600 - read/write access to the file + + Example writing file contents with read/write permissions for the application user: + ``` + dat := []byte("sensitive data") + if err := os.WriteFile("file.txt", dat, 0600); err != nil { + log.Fatal(err) + } + ``` + + For all other values please see: + https://en.wikipedia.org/wiki/File-system_permissions#Numeric_notation + metadata: + shortDescription: "Incorrect default permissions" + cwe: "CWE-276" + owasp: + - "A5:2017-Broken Access Control" + - "A01:2021-Broken Access Control" + security-severity: "Medium" + category: "security" + severity: "WARNING" +- id: go_filesystem_rule-tempfiles + languages: + - "go" + patterns: + - pattern-either: + - pattern: | + os.WriteFile("$ARG", ...) + - pattern: | + ioutil.WriteFile("$ARG", ...) + - pattern: | + os.OpenFile("$ARG", <... os.O_CREATE ...>, ...) + - pattern: | + os.Create("$ARG") + - metavariable-regex: + metavariable: "$ARG" + regex: "(/tmp/.*|/var/tmp/.*)" + message: | + The application was found creating files in shared system temporary directories + (`/tmp` or `/var/tmp`) without using the `os.CreateTemp` function. Depending + on how the application uses this temporary file, an attacker may be able to create + symlinks that point to other files prior to the application creating or writing + to the target file, leading to unintended files being created or overwritten. + + Example using `os.CreateTemp` in an application restricted directory: + ``` + // assumes /opt/appdir/ is chown'd to the running application user + if err := os.MkdirAll("/opt/appdir/restricted", 0700); err != nil { + log.Fatal(err) + } + + // create a temporary file in the restricted directory in the form of temp-952569059.txt + f, err := os.CreateTemp("/opt/appdir/restricted", "temp-*.txt") + if err != nil { + log.Fatal(err) + } + + defer f.Close() + // clean up on exit + defer os.Remove(f.Name()) + // work with file + ``` + metadata: + shortDescription: "Creation of temporary file with insecure permissions" + cwe: "CWE-378" + owasp: + - "A5:2017-Broken Access Control" + - "A01:2021-Broken Access Control" + security-severity: "Medium" + category: "security" + severity: "WARNING" +- id: go_filesystem_rule-ziparchive + languages: + - "go" + mode: "taint" + pattern-sources: + - pattern: "zip.OpenReader(...)" + - pattern: "tar.OpenReader(...)" + pattern-sanitizers: + - patterns: + - pattern-either: + - pattern: | + $CLEAN := $PKG.Clean(...) + ... + if !strings.HasPrefix($CLEAN, "...") {...} + - pattern: | + $CLEAN := $PKG.Clean(...) + ... + if strings.HasPrefix($CLEAN, "...") {...} + - pattern: | + $CLEAN := $PKG.Clean(...) + ... + if strings.HasPrefix($CLEAN, "...") == false {...} + - metavariable-regex: + metavariable: "$PKG" + regex: "^((file)?path)$" + pattern-sinks: + - pattern: "filepath.Join(...)" + message: | + The application may be vulnerable to a path traversal if it extracts untrusted archive files. + This vulnerability is colloquially known as 'Zip Slip'. Archive files may contain folders + which, + when extracted, may write outside of the intended directory. This is exploited by including + path traversal characters such as `../../other/directory` to overwrite or place files in system + or application directories. + + Extra care must be taken when extracting archive files as there are numerous concerns: + + - Limit the size of the zip archive as it may contain "Zip Bombs", files that extract to + extremely + large sizes. + - If possible, generate unique filenames instead of using the archives file names, as it may be + possible for users to overwrite files if the filenames are the same. + - Validate file paths are written with a prefixed, known trusted directory. + - Only process regular files and not symbolic links, as some applications may attempt to + read/follow + the symbolic link, leading to arbitrary file read / write vulnerabilities. + + + Example of securely processing an archive file: + ``` + r, err := zip.OpenReader("trusted.zip") + if err != nil { + log.Fatal(err) + } + + // Ensure archive contains only the expected number of files + const expectedFileCount = 10 + if len(r.File) > expectedFileCount { + log.Fatalf("too many files in archive: %d\n", len(r.File)) + } + + // One approach is to sum up all files before attempting to process + // them. + const totalAllowedSize = 1024 * 1024 * 10 // 10MB + var totalSize uint64 + for _, f := range r.File { + totalSize += f.UncompressedSize64 + } + + if totalSize > totalAllowedSize { + log.Fatalf("archive exceeds total allowed size: %d\n", totalSize) + } + + // configure a max size per file allowed + const maxFileSize = 1024 * 1024 // 1 MB + + // set restricted basePath + const basePath = "/var/restricted/" + + // iterate over the files in the archive + for _, f := range r.File { + + // Ensure uncompressed size does not exceed our allowed file size + if f.UncompressedSize64 > maxFileSize { + log.Printf("skipping file as it exceeds maxFileSize: %s\n", f.Name) + continue + } + + // Ensure file is a regular file and not a symbolic link or has other mode type + // bits set + if !f.Mode().IsRegular() { + log.Printf("skipping non regular file: %s\n", f.Name) + continue + } + + // if possible consider not using the name at all, but generating a random id instead. + // If the filename must be used, extract the base name and not folder path information + name := filepath.Base(f.Name) + + // Join the file name to the basePath. + resolvedPath := filepath.Join(basePath, name) + + // Application must still verify the path is prefixed by the basePath + if !strings.HasPrefix(resolvedPath, basePath) { + log.Fatal("path does not start with basePath") + } + + // process / work with file + } + ``` + + If the application must process directory names as well, use the following code: + ``` + // Join the cleaned name to the basePath, note if 'name' starts with `../../` it + // will still allow for traversal, so you _must_ verify the path prefix below + resolvedPath := filepath.Join(basePath, filepath.Clean(name)) + + // Application must still verify the path is prefixed by the basePath + if !strings.HasPrefix(resolvedPath, basePath) { + log.Fatal("path does not start with basePath") + } + + // process / work with file + ``` + metadata: + shortDescription: "Improper limitation of a pathname to a restricted directory + ('Path Traversal')" + cwe: "CWE-22" + owasp: + - "A5:2017-Broken Access Control" + - "A01:2021-Broken Access Control" + security-severity: "Medium" + category: "security" + severity: "WARNING" +- id: go_http_rule-http-serve + languages: + - "go" + patterns: + - pattern-inside: | + import "net/http" + ... + - pattern-either: + - pattern: "http.ListenAndServe(...)" + - pattern: "http.ListenAndServeTLS(...)" + - pattern: "http.Serve(...)" + - pattern: "http.ServeTLS(...)" + - patterns: + - pattern-not-inside: | + &http.Server{ + ..., + ReadHeaderTimeout: ..., + ..., + } + - pattern-not-inside: | + &http.Server{ + ..., + ReadTimeout: ..., + ..., + } + - pattern-not-inside: | + $S = &http.Server{ + ..., + } + $S.ReadHeaderTimeout = ... + ... + - pattern-not-inside: | + $S = &http.Server{ + ..., + } + $S.ReadTimeout = ... + ... + - pattern: | + &http.Server{ + ..., + } + message: | + Go's `net/http` serve functions may be vulnerable to resource consumption attacks if timeouts + are not properly configured + prior to starting the HTTP server. An adversary may open up thousands of connections but never + complete sending all data, + or never terminate the connections. This may lead to the server no longer accepting new + connections. + + To protect against this style of resource consumption attack, timeouts should be set in the + `net/http` server prior to calling + the listen or serve functions. What this means is that the default `http.ListenAndServe` and + `http.Serve` functions should not + be used in a production setting as they are unable to have timeouts configured. Instead a + custom `http.Server` object must be + created with the timeouts configured. + + Example setting timeouts on a `net/http` server: + ``` + // All values chosen below are dependent on application logic and + // should be tailored per use-case + srv := &http.Server{ + Addr: "localhost:8000", + // ReadHeaderTimeout is the amount of time allowed to read + // request headers. The connection's read deadline is reset + // after reading the headers and the Handler can decide what + // is considered too slow for the body. If ReadHeaderTimeout + // is zero, the value of ReadTimeout is used. If both are + // zero, there is no timeout. + ReadHeaderTimeout: 15 * time.Second, + + // ReadTimeout is the maximum duration for reading the entire + // request, including the body. A zero or negative value means + // there will be no timeout. + // + // Because ReadTimeout does not let Handlers make per-request + // decisions on each request body's acceptable deadline or + // upload rate, most users will prefer to use + // ReadHeaderTimeout. It is valid to use them both. + ReadTimeout: 15 * time.Second, + + // WriteTimeout is the maximum duration before timing out + // writes of the response. It is reset whenever a new + // request's header is read. Like ReadTimeout, it does not + // let Handlers make decisions on a per-request basis. + // A zero or negative value means there will be no timeout. + WriteTimeout: 10 * time.Second, + + // IdleTimeout is the maximum amount of time to wait for the + // next request when keep-alives are enabled. If IdleTimeout + // is zero, the value of ReadTimeout is used. If both are + // zero, there is no timeout. + IdleTimeout: 30 * time.Second, + } + + // For per request timeouts applications can wrap all `http.HandlerFunc(...)` in + // `http.TimeoutHandler`` and specify a timeout, but note the TimeoutHandler does not + // start ticking until all headers have been read. + + // Listen with our custom server with timeouts configured + if err := srv.ListenAndServe(); err != nil { + log.Fatal(err) + } + ``` + For more information on the `http.Server` timeouts, see: https://pkg.go.dev/net/http#Server + + For information on setting request based timeouts, see: + https://pkg.go.dev/net/http#TimeoutHandler + + For more information on the Slowloris attack see: + https://en.wikipedia.org/wiki/Slowloris_(computer_security) + metadata: + shortDescription: "Allocation of resources without limits or throttling" + cwe: "CWE-770" + owasp: + - "A6:2017-Security Misconfiguration" + - "A05:2021-Security Misconfiguration" + security-severity: "Low" + category: "security" + severity: "WARNING" +- id: go_injection_rule-ssrf + languages: + - "go" + mode: taint + # At the moment we cannot use the function calls both as sources and sinks + # (which would be a valid use case for SSRF); this would require the + # https://semgrep.dev/docs/writing-rules/experiments/taint-labels/ which is + # experimental. + pattern-sources: + - patterns: + - pattern-not-inside: | + import "testing" + ... + - pattern-either: + - pattern: "os.Stdin" + - pattern: "os.Getenv(...)" + - pattern: | + ($REQ: *http.Request).$ANY + - pattern: | + ($REQ: http.Request).$ANY + - patterns: + - pattern: "($REQ : *http.Request)" + - pattern-inside: | + func $FUNC( $W http.ResponseWriter, $R *http.Request, ...) { + ... + } + pattern-sinks: + - pattern: "http.Head(...)" + - pattern: "http.Get(...)" + - pattern: "http.Post(...)" + - pattern: "http.PostForm(...)" + - pattern: "http.NewRequest($METHOD,...)" + - pattern: "http.DefaultClient.Head(...)" + - pattern: "http.DefaultClient.Get(...)" + - pattern: "http.DefaultClient.Post(...)" + - pattern: "http.DefaultClient.PostForm(...)" + - pattern: "http.NewRequestWithContext($CONTEXT, $METHOD, ...)" + - pattern: "ftp.Dial(...)" + - pattern: "ldap.DialURL(...)" + - pattern: "smtp.Dial(...)" + - pattern: "retryablehttp.NewRequest($METHOD, ..., $BODY)" + - patterns: + - pattern-inside: | + $C := retryablehttp.NewClient() + ... + - pattern-either: + - pattern: "$C.Get(...)" + - pattern: "$C.Post(..., $BODYTYPE, $BODY)" + - pattern: "$C.PostForm(..., $VALS)" + - pattern: "$C.Head(...)" + pattern-propagators: + - pattern: $R := $D.NewDecoder($P) + from: $P + to: $R + - pattern: $S.Decode(&$P) + from: $S + to: $P + - pattern: $S.Decode($P) + from: $S + to: $P + - pattern: $S.Unmarshal($B, &$P) + from: $B + to: $P + - pattern: $S.Unmarshal($B, $P) + from: $B + to: $P + message: | + Server-Side-Request-Forgery (SSRF) exploits backend systems that initiate requests to third + parties. + If user input is used in constructing or sending these requests, an attacker could supply + malicious + data to force the request to other systems or modify request data to cause unwanted actions. + + Ensure user input is not used directly in constructing URLs or URIs when initiating requests + to third party + systems from back end systems. Care must also be taken when constructing payloads using user + input. Where + possible restrict to known URIs or payloads. Consider using a server side map where key's are + used to return + URLs such as `https://site/goto?key=1` where `{key: 1, url: 'http://some.url/', key: 2, url: + 'http://...'}`. + + If you must use user supplied input for requesting URLs, it is strongly recommended that the + HTTP client + chosen allows you to customize and block certain IP ranges at the network level. By blocking + RFC 1918 + addresses or other network address ranges, you can limit the severity of a successful SSRF + attack. Care must + also be taken to block certain protocol or address formatting such as IPv6. + + If you can not block address ranges at the client level, you may want to run the HTTP client + as a protected + user, or in a protected network where you can apply IP Table or firewall rules to block access + to dangerous + addresses. Finally, if none of the above protections are available, you could also run a + custom HTTP proxy + and force all requests through it to handle blocking dangerous addresses. + + Example HTTP client that disallows access to loopback and RFC-1918 addresses + ``` + // IsDisallowedIP parses the ip to determine if we should allow the HTTP client to continue + func IsDisallowedIP(hostIP string) bool { + ip := net.ParseIP(hostIP) + return ip.IsMulticast() || ip.IsUnspecified() || ip.IsLoopback() || ip.IsPrivate() + } + + // SafeTransport uses the net.Dial to connect, then if successful check if the resolved + // ip address is disallowed. We do this due to hosts such as localhost.lol being resolvable to + // potentially malicious URLs. We allow connection only for resolution purposes. + func SafeTransport(timeout time.Duration) *http.Transport { + return &http.Transport{ + DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) { + c, err := net.DialTimeout(network, addr, timeout) + if err != nil { + return nil, err + } + ip, _, _ := net.SplitHostPort(c.RemoteAddr().String()) + if IsDisallowedIP(ip) { + return nil, errors.New("ip address is not allowed") + } + return c, err + }, + DialTLS: func(network, addr string) (net.Conn, error) { + dialer := &net.Dialer{Timeout: timeout} + c, err := tls.DialWithDialer(dialer, network, addr, &tls.Config{}) + if err != nil { + return nil, err + } + + ip, _, _ := net.SplitHostPort(c.RemoteAddr().String()) + if IsDisallowedIP(ip) { + return nil, errors.New("ip address is not allowed") + } + + err = c.Handshake() + if err != nil { + return c, err + } + + return c, c.Handshake() + }, + TLSHandshakeTimeout: timeout, + } + } + + func httpRequest(requestUrl string) { + const clientConnectTimeout = time.Second * 10 + httpClient := &http.Client{ + Transport: SafeTransport(clientConnectTimeout), + } + resp, err := httpClient.Get(requestUrl) + if err != nil { + log.Fatal(err) + } + defer resp.Body.Close() + // work with resp + } + ``` + + For more information on SSRF see OWASP: + https://owasp.org/www-community/attacks/Server_Side_Request_Forgery + metadata: + shortDescription: "Server Side Request Forgery (SSRF)" + cwe: "CWE-918" + owasp: + - "A1:2017-Injection" + - "A10:2021-Server-Side Request Forgery" + security-severity: "Medium" + category: "security" + severity: "WARNING" +- id: go_injection_rule-template-injection + languages: + - "go" + patterns: + - pattern-either: + - patterns: + - pattern: "template.HTML($IN)" + - pattern-not: "template.HTML(\"...\")" + - patterns: + - pattern: "template.JS($IN)" + - pattern-not: "template.JS(\"...\")" + - patterns: + - pattern: "template.URL($IN)" + - pattern-not: "template.URL(\"...\")" + - patterns: + - pattern: "template.HTMLAttr($IN)" + - pattern-not: "template.HTMLAttr(\"...\")" + message: | + Cross Site Scripting (XSS) is an attack which exploits a web application or system to treat + user input + as markup or script code. It is important to encode the data depending on the specific context + it + is used in. There are at least six context types: + + - Inside HTML tags `
context 1
` + - Inside attributes: `
` + - Inside event attributes `` + - Inside script blocks: `` + - Unsafe element HTML assignment: `element.innerHTML = "context 5"` + - Inside URLs: `link` + + Script blocks alone have multiple ways they need to be encoded. Extra care must be taken if + user input + is ever output inside of script tags. + + User input that is displayed within the application must be encoded, sanitized or validated + to ensure it cannot be treated as HTML or executed as Javascript code. Care must also be + taken + to not mix server-side templating with client-side templating, as the server-side templating + will + not encode things like {{ 7*7 }} which may execute client-side templating features. + + It is _NOT_ advised to encode user input prior to inserting into a data store. The data will + need to be + encoded depending on context of where it is output. It is much safer to force the displaying + system to + handle the encoding and not attempt to guess how it should be encoded. + + Use of the following template types with user input denotes a security risk: + + - [template.HTML](https://pkg.go.dev/html/template#HTML) + - [template.JS](https://pkg.go.dev/html/template#JS) + - [template.URL](https://pkg.go.dev/html/template#URL) + - [template.HTMLAttr](https://pkg.go.dev/html/template#HTMLAttr) + + Either remove these types from the application or hardcode as const strings prior + to conversion: + ``` + testTemplate, err := template.New("testTemplate").Funcs(template.FuncMap{ + "SafeHTML": func() template.HTML { + const safeHTML = "
hardcoded, safe html
" + return template.HTML(safeHTML) + }, + }).Parse(`{{ SafeHTML }}`) + if err != nil { + log.Fatal(err) + } + + if err := testTemplate.Execute(os.Stdout, nil); err != nil { + log.Fatal(err) + } + ``` + metadata: + shortDescription: "Improper neutralization of input during web page generation + ('Cross-site Scripting')" + cwe: "CWE-79" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "Medium" + category: "security" + severity: "WARNING" +- id: go_leak_rule-pprof-endpoint + languages: + - "go" + patterns: + - pattern-inside: | + import ( + "net/http/pprof" + ) + ... + - pattern-either: + - pattern: "http.ListenAndServe(...)" + - pattern: "http.ListenAndServeTLS(...)" + - pattern: "http.Serve(...)" + - pattern: "http.ServeTLS(...)" + message: | + Go has a built in profiling service that is enabled by starting an HTTP server with + `net/http/pprof` imported. The `/debug/pprof` endpoint does not require any + authentication and can be accessed by anonymous users. This profiling endpoint + can leak sensitive information and should not be enabled in production. + + To remediate this, remove the `net/http/pprof` import from the file. + metadata: + shortDescription: "Active debug code (pprof enabled)" + cwe: "CWE-489" + owasp: + - "A6:2017-Security Misconfiguration" + - "A05:2021-Security Misconfiguration" + security-severity: "Medium" + category: "security" + severity: "ERROR" +- id: go_memory_rule-integer-overflow + languages: + - "go" + patterns: + - pattern-either: + - patterns: + - pattern-inside: | + $X, ... := strconv.Atoi(...) + ... + - pattern-either: + - pattern: "int32($X)" + - pattern: "int16($X)" + message: | + Golang's `int` type size depends on the architecture of where the application is running. For + 32-bit systems, `int` is + 32-bit, for 64-bit systems, `int` will be 64-bit. By calling `strconv.Atoi` with a large + number, the integer may overflow + if the `int` return value is type converted into a smaller type (`int32` or `int16`). This + could cause unexpected application + behavior depending on how the resultant value is used. + + Prior to running any type conversion, check that the value returned from `strconv.Atoi` will + fit in the resulting integer. + + Example of checking the return value before type conversion: + ``` + bigValue, _ := strconv.Atoi("32768") + if bigValue > math.MaxInt16 { + log.Fatal("value too large to fit in int16") + } + value := int16(bigValue) + fmt.Println(value) + ``` + + For more information on integer min/max constants see: https://pkg.go.dev/math#pkg-constants + metadata: + shortDescription: "Integer overflow or wraparound" + cwe: "CWE-190" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "Medium" + category: "security" + severity: "ERROR" +- id: go_memory_rule-memoryaliasing + languages: + - "go" + patterns: + - pattern-either: + - pattern: | + for ..., $ARG := range $SLICE { + <... &($ARG) ...> + } + - pattern: | + for ..., $ARG := range $SLICE { + <... func() { <... &$ARG ...> } ...> + } + - pattern: | + for ..., $ARG := range $SLICE { + <... $X(..., <... &$ARG ...>, ...) ...> + } + - pattern-not: | + for ..., $ARG := range $SLICE { + <... *$ARG ...> + } + - pattern-not-inside: |- + for ..., $ARG := range $SLICE { return ... } + message: | + Go's `for ... range` statements create an iteration variable for each iteration of the loop. + By taking the address of this iteration variable, the value of the address will be re-used + and always point to the same location in memory. This can have unexpected behavior if the + address is stored or re-used. + + This can be fixed by: + - Not referencing the address of the variable + - Re-assigning the iteration variable to a new variable + - Using the address of the indexed variable + + Example not referencing the address: + ``` + type someStruct struct { + x int + } + + for _, n := range []someStruct{{1}, {2}, {3}, {4}} { + fmt.Printf("%d\n", n.x) + } + ``` + + Example reassigning the iteration variable to a new variable: + ``` + type someStruct struct { + x int + } + + for _, n := range []someStruct{{1}, {2}, {3}, {4}} { + p := n + fmt.Printf("%p\n", &p) + } + ``` + + Example using the address of the indexed variable: + ``` + type someStruct struct { + x int + } + + structData := []someStruct{{1}, {2}, {3}, {4}} + for idx := range structData { + fmt.Printf("%p\n", &structData[idx]) + } + ``` + + For more information on how the `for ... range` statement works see: + https://go.dev/ref/spec#For_statements + metadata: + shortDescription: "Incorrect access of indexable resource ('Range Error')" + cwe: "CWE-118" + owasp: + - "A6:2017-Security Misconfiguration" + - "A05:2021-Security Misconfiguration" + security-severity: "Info" + category: "security" + severity: "WARNING" +- id: go_network_rule-bind-to-all-interfaces + languages: + - "go" + patterns: + - pattern-either: + - pattern: "net.Listen(..., \"$ADDR\")" + - pattern: "tls.Listen(..., \"$ADDR\", ...)" + - metavariable-regex: + metavariable: "$ADDR" + regex: "^(0\\.0\\.0\\.0|\\[::\\])?(:[0-9]*)?$" + message: | + Binding to all network interfaces can potentially open up a service to + traffic on unintended interfaces, that may not be properly documented or + secured. By passing "0.0.0.0" as the address to the `Listen` family of functions, + the application will bind to all interfaces. + + Consider passing in the interface ip address through an environment variable, + configuration file, or by determining the primary interface(s) IP address. + + Example getting the IP address from an environment variable `IP_ADDRESS`: + ``` + addr := os.Getenv("IP_ADDRESS") + listener, err := net.Listen("tcp", addr) + if err != nil { + log.Fatal(err) + } + ``` + metadata: + shortDescription: "Binding to an unrestricted IP address" + cwe: "CWE-1327" + owasp: + - "A6:2017-Security Misconfiguration" + - "A05:2021-Security Misconfiguration" + security-severity: "Low" + category: "security" + severity: "WARNING" +- id: go_sql_rule-concat-sqli + languages: + - "go" + mode: taint + pattern-sources: + - patterns: + - pattern: "fmt.Sprintf(...)" + - pattern-not: | + fmt.Sprintf("...", "...") + - patterns: + - pattern: | + "..." + $X + - pattern-not: | + "..." + "..." + - pattern: | + ($SB : strings.Builder).String() + pattern-sinks: + - patterns: + - pattern: "$DB.$METHOD(...)" + - metavariable-regex: + metavariable: $METHOD + regex: "^(Exec(Context)?|Query(Context)?|QueryRow(Context)?)$" + message: | + SQL Injection is a critical vulnerability that can lead to data or system compromise. By + dynamically generating SQL query strings, user input may be able to influence the logic of + the SQL statement. This could lead to an adversary accessing information they should + not have access to or in some circumstances, being able to execute OS functionality or code. + + Replace all dynamically generated SQL queries with parameterized queries. In situations where + dynamic queries must be created, never use direct user input, but instead use a map or + dictionary of valid values and resolve them using a user supplied key. + + For example, some database drivers do not allow parameterized queries for `>` or `<` comparison + operators. In these cases, do not use a user supplied `>` or `<` value, but rather have the + user + supply a `gt` or `lt` value. The alphabetical values are then used to look up the `>` and `<` + values to be used in the construction of the dynamic query. The same goes for other queries + where + column or table names are required but cannot be parameterized. + + Example using parameterized queries with `sql.Query`: + ``` + rows, err := db.Query("SELECT * FROM users WHERE userName = ?", userName) + if err != nil { + return nil, err + } + defer rows.Close() + for rows.Next() { + // ... process rows + } + ``` + + For more information on SQL Injection see OWASP: + https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html + metadata: + shortDescription: "Improper neutralization of special elements used in an SQL + command ('SQL Injection')" + cwe: "CWE-89" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "High" + category: "security" + severity: "WARNING" +- id: go_subproc_rule-subproc + languages: + - "go" + patterns: + - pattern-either: + - patterns: + - pattern: "exec.CommandContext($CTX, $EXE, ...)" + - pattern-not: "exec.CommandContext($CTX, \"...\", ...)" + - patterns: + - pattern: "exec.Command($EXE, ...)" + - pattern-not: "exec.Command(\"...\", ...)" + - patterns: + - pattern: "syscall.ForkExec($EXE, ...)" + - pattern-not: "syscall.ForkExec(\"...\", ...)" + - patterns: + - pattern: "syscall.StartProcess($EXE, ...)" + - pattern-not: "syscall.StartProcess(\"...\", ...)" + message: | + OS command injection is a critical vulnerability that can lead to a full system + compromise as it may allow an adversary to pass in arbitrary commands or arguments + to be executed. + + User input should never be used in constructing commands or command arguments + to functions which execute OS commands. This includes filenames supplied by + user uploads or downloads. + + Ensure your application does not: + + - Use user-supplied information in the process name to execute. + - Use user-supplied information in an OS command execution function which does + not escape shell meta-characters. + - Use user-supplied information in arguments to OS commands. + + The application should have a hardcoded set of arguments that are to be passed + to OS commands. If filenames are being passed to these functions, it is + recommended that a hash of the filename be used instead, or some other unique + identifier. It is strongly recommended that a native library that implements + the same functionality be used instead of using OS system commands, due to the + risk of unknown attacks against third party commands. + + If operating in Windows environments, when specifying the OS command, ensure + the application uses the full path + information, otherwise the OS may attempt to look up which process to execute + and could be vulnerable to untrusted search path vulnerabilities (CWE-426). + + Example of safely executing an OS command: + ``` + userData := []byte("user data") + // create a temporary file in the application specific directory + f, err := ioutil.TempFile("/var/app/restricted", "temp-*.dat") + if err != nil { + log.Fatal(err) + } + + if _, err := f.Write(userData); err != nil { + log.Fatal(err) + } + + if err := f.Close(); err != nil { + log.Fatal(err) + } + + // pass the full path to the binary and the name of the temporary file + // instead of any user supplied filename + out, err := exec.Command("/bin/cat", f.Name()).Output() + if err != nil { + log.Fatal(err) + } + ``` + + For more information on OS command injection, see OWASP's guide: + https://cheatsheetseries.owasp.org/cheatsheets/OS_Command_Injection_Defense_Cheat_Sheet.html + metadata: + shortDescription: "Improper neutralization of special elements used in an OS command ('OS Command Injection')" + cwe: "CWE-78" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "High" + category: "security" + severity: "WARNING" +- id: go_unsafe_rule-unsafe + languages: + - "go" + patterns: + - pattern-either: + - pattern: "unsafe.Alignof(...)" + - pattern: "unsafe.Offsetof(...)" + - pattern: "unsafe.Sizeof(...)" + - pattern: "unsafe.Pointer(...)" + message: | + The `unsafe` package in Go allows low-level access to memory management features. + This includes pointers and direct access to memory. The Go compiler will no longer + be able to enforce type safety when working with the `unsafe` pointer types. + + While powerful, access to these functions can lead to many security related issues + such as: + + - [Buffer overflows](https://owasp.org/www-community/vulnerabilities/Buffer_Overflow) which + can lead to code execution. + - [Use after free](https://owasp.org/www-community/vulnerabilities/Using_freed_memory) which + can lead to code execution. + - [Information/Memory leaks](https://owasp.org/www-community/vulnerabilities/Memory_leak) + which can leak sensitive information, including data which can + defeat other protection mechanisms or cause the system to run out of memory. + + Unless required, all calls to the `unsafe` package should be removed. + metadata: + shortDescription: "Use of inherently dangerous function (unsafe package)" + cwe: "CWE-242" + owasp: + - "A9:2017-Using Components with Known Vulnerabilities" + - "A06:2021-Vulnerable and Outdated Components" + security-severity: "High" + category: "security" + severity: "INFO" +- id: java_cookie_rule-CookieInsecure + languages: + - "java" + patterns: + - pattern: | + $X.servlet.http.Cookie $C = new $X.servlet.http.Cookie(..., ...); + ... + ($X.servlet.http.HttpServletResponse $RESP).addCookie($C); + - pattern-not-inside: | + $X.servlet.http.Cookie $C = new $X.servlet.http.Cookie(..., ...); + ... + $C.setSecure(true); + ... + ($X.servlet.http.HttpServletResponse $RESP).addCookie($C); + message: | + The `Secure` attribute when set to `true` protects the cookie value from being being + transmitted over clear text + communication paths such as HTTP. By enabling this protection, the cookie will only be sent + over HTTPS. + + Example of protecting a `Cookie`: + ``` + // Create an Secure cookie. + Cookie someCookie = new Cookie("SomeCookieName", "SomeValue"); + // Set Secure flag to true + someCookie.setSecure(true); + ``` + + For more information see: + https://jakarta.ee/specifications/servlet/4.0/apidocs/javax/servlet/http/cookie#setSecure-boolean- + + Session cookies should be configured with the following security directives: + + - [HTTPOnly](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#restrict_access_to_cookies) + - [SameSite](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite) + - [Secure](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#restrict_access_to_cookies) + severity: "WARNING" + metadata: + shortDescription: "Sensitive cookie in HTTPS session without 'Secure' attribute" + category: "security" + cwe: "CWE-614" + owasp: + - "A6:2017-Security Misconfiguration" + - "A05:2021-Security Misconfiguration" + technology: + - "java" + security-severity: "Low" +- id: java_cookie_rule-HttpResponseSplitting + languages: + - "java" + mode: "taint" + pattern-sanitizers: + - patterns: + - pattern-inside: | + $STR.replaceAll($REPLACER, "..."); + ... + - pattern: "$STR" + - metavariable-regex: + metavariable: "$REPLACER" + regex: ".*\\[(?=.*\\\\r)(?=.*\\\\n).*\\]\\+" + - pattern: "org.apache.commons.text.StringEscapeUtils.escapeJava($STR);" + pattern-sinks: + - pattern: "new javax.servlet.http.Cookie(\"$KEY\", ...);" + - patterns: + - pattern-inside: | + $C = new javax.servlet.http.Cookie("$KEY", ...); + ... + - pattern: "$C.setValue(...);" + pattern-sources: + - pattern: "(javax.servlet.http.HttpServletRequest $REQ).getParameter(...);" + - pattern: "(javax.servlet.http.HttpServletRequest $REQ).getParameterNames();" + - pattern: "(javax.servlet.http.HttpServletRequest $REQ).getParameterValues(...);" + - pattern: "(javax.servlet.http.HttpServletRequest $REQ).getParameterMap();" + - pattern: "(javax.servlet.http.HttpServletRequest $REQ).getHeader(...);" + - pattern: "(javax.servlet.http.HttpServletRequest $REQ).getPathInfo();" + message: | + HTTP Response Splitting is a vulnerability where Carriage Return (CR `\r`) and Line Feed (LF + `\n`) + characters are introduced into an HTTP header from user-supplied input. By injecting the + `\r\n` + character sequence, an adversary could potentially modify how the response is interpreted by + the + client or any downstream caching services. This could allow an adversary to poison the cache + data or execute Cross-Site Scripting (XSS) attacks. + + Some Java application servers such as [Apache Tomcat](https://tomcat.apache.org/) as of version + 8.0, newer versions of Jetty and other servers that implement the [RFC 6265 Standard](https://datatracker.ietf.org/doc/html/rfc6265) will + disallow `\r' and '\n` characters characters from being set in cookies. If your application server does not + automatically provide this functionality, user-supplied input that is used in cookie keys or + values must be validated. + + Example of validating cookies to only allow valid characters: + ``` + // throws an IllegalArgumentException if the provided value contains invalid characters + public void validateRfc6265CookieValue(String value) throws IllegalArgumentException { + char[] chars = value.toCharArray(); + + // iterate over every character + for (int i = 0; i < chars.length; i++) { + char c = chars[i]; + + // check for any characters below 0x21 as well as: '"' ',' ';' '\' and 0x7f. + if (c < 0x21 || c == '"' || c == ',' || c == ';' || c == '\\' || c == 0x7f) { + throw new IllegalArgumentException("Invalid character in cookie detected: + {0}".format(Integer.toString(c))); + } + } + } + ``` + + Alternatively, you could use a string escape package such as + [Apache Commons Text](https://commons.apache.org/proper/commons-text/) to escape the input: + ``` + public String escapeValue(String value) { + return StringEscapeUtils.escapeJava(value); + } + ``` + + For more information on response splitting attacks see OWASP: + https://owasp.org/www-community/attacks/HTTP_Response_Splitting + severity: "WARNING" + metadata: + shortDescription: "Improper neutralization of CRLF sequences in HTTP headers ('HTTP + Response Splitting')" + category: "security" + cwe: "CWE-113" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + technology: + - "java" + security-severity: "High" +- id: java_cookie_rule-RequestParamToHeader + languages: + - "java" + mode: "taint" + pattern-sanitizers: + - patterns: + - pattern-inside: | + $STR.replaceAll("$INPUT", "..."); + ... + - pattern: "$STR" + - metavariable-regex: + metavariable: "$INPUT" + regex: ".*\\[(?=.*\\\\r)(?=.*\\\\n).*\\]\\+" + - pattern: "org.apache.commons.text.StringEscapeUtils.unescapeJava(...);" + pattern-sinks: + - pattern: "($X.servlet.http.HttpServletResponse $RES).setHeader(\"$KEY\", ...);" + - pattern: "($X.servlet.http.HttpServletResponse $RES).addHeader(\"$KEY\", ...);" + - pattern: "($X.servlet.http.HttpServletResponseWrapper $WRP).setHeader(\"$KEY\", + ...);" + - pattern: "($X.servlet.http.HttpServletResponseWrapper $WRP).addHeader(\"$KEY\", + ...);" + pattern-sources: + - pattern: "($X.servlet.http.HttpServletRequest $REQ).getParameter(...);" + - pattern: "($X.servlet.http.HttpServletRequest $REQ).getParameterNames();" + - pattern: "($X.servlet.http.HttpServletRequest $REQ).getParameterValues(...);" + - pattern: "($X.servlet.http.HttpServletRequest $REQ).getParameterMap();" + - pattern: "($X.servlet.http.HttpServletRequest $REQ).getHeader(...);" + - pattern: "($X.servlet.http.HttpServletRequest $REQ).getPathInfo();" + message: | + HTTP Response Splitting is a vulnerability where Carriage Return (CR `\r`) and Line Feed (LF + `\n`) + characters are introduced into an HTTP header from user-supplied input. By injecting the + `\r\n` + character sequence, an adversary could potentially modify how the response is interpreted by + the + client or any down stream caching services. This could allow an adversary to poison the cache + data or execute Cross-Site Scripting (XSS) attacks. + + Some Java application servers such as [Apache Tomcat](https://tomcat.apache.org/) will + automatically encode + characters from being set in response headers as a space `0x20` character. If your application + server does + not automatically provide this functionality, user-supplied input that is used in header keys + or values must be + validated. + + Example of validating headers to only allow valid characters: + ``` + // throws an IllegalArgumentException if the provided value contains invalid characters + public void validateHeader(String value) throws IllegalArgumentException { + char[] chars = value.toCharArray(); + + // iterate over every character + for (int i = 0; i < chars.length; i++) { + char c = chars[i]; + + // check for any characters below 0x21 as well as: '"' ',' ';' '\' and 0x7f. + if (c < 0x21 || c == '"' || c == ',' || c == ';' || c == '\\' || c == 0x7f) { + throw new IllegalArgumentException("Invalid character in cookie detected: + {0}".format(Integer.toString(c))); + } + } + } + ``` + + Alternatively, you could use a string escape package such as + [Apache Commons Text](https://commons.apache.org/proper/commons-text/) to escape the input: + ``` + public String escapeValue(String value) { + return StringEscapeUtils.escapeJava(value); + } + ``` + + For more information on response splitting attacks see OWASP: + https://owasp.org/www-community/attacks/HTTP_Response_Splitting + severity: "ERROR" + metadata: + shortDescription: "Improper neutralization of CRLF sequences in HTTP headers ('HTTP + Response Splitting')" + category: "security" + cwe: "CWE-113" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + technology: + - "java" + security-severity: "High" +- id: java_cors_rule-PermissiveCORSInjection + languages: + - "java" + mode: "taint" + pattern-sources: + - pattern: "(HttpServletRequest $REQ).getParameter(...)" + - pattern: "(HttpServletRequest $REQ).getHeader(...)" + - pattern: "(HttpServletRequest $REQ).getPathInfo()" + - pattern: "(HttpServletRequest $REQ).getQueryString()" + - pattern: "(HttpServletRequest $REQ).getAttribute(...)" + - pattern: "(HttpServletRequest $REQ).getSession().getAttribute(...)" + - pattern: "(HttpServletRequest $REQ).getServletContext().getAttribute(...)" + - pattern: "(HttpServletRequest $REQ).getParameterValues(...)" + - pattern: "(HttpServletRequest $REQ).getParameterNames()" + - pattern: "(HttpServletRequest $REQ).getParameterMap()" + pattern-sinks: + - patterns: + - pattern-either: + - pattern: "(HttpServletResponse $RES).setHeader(\"$HEADER\", ...)" + - pattern: "(HttpServletResponse $RES).addHeader(\"$HEADER\", ...)" + - metavariable-regex: + metavariable: "$HEADER" + regex: "(?i)(Access-Control-Allow-Origin)" + message: | + This application potentially allows user-supplied input into the value of the + `Access-Control-Allow-Origin` response header. This header is part of the + [Cross-Origin Resource Sharing](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) CORS + specification. By allowing user input to specify which domains can communicate with this + server, + an adversary could exploit a weakness in this server to force clients to send credentials (such + as session + identifiers) to the adversary's server. + + For the above attack to work, the application would need to suffer from an additional + vulnerability, + such as Cross-Site Scripting (XSS). + + To remediate this issue, do not use user-supplied information when calling + `HttpServletResponse.setHeader` or `HttpServletResponse.addHeader` + for the `Access-Control-Allow-Origin` header's value. Instead, hardcode the allowed domain(s) + and reference them in a lookup + table: + Example allowing dynamic but safe domains in `Access-Control-Allow-Origin`: + + ``` + // this data should be in the class constructor or taken from a trusted datasource + Map allowedDomains = new HashMap(); + allowedDomains.put("sub1", "sub1.example.com"); + allowedDomains.put("sub2", "sub2.example.com"); + + // extract the allowedDomain parameters value as a key to look up which domain to provide + via the allowedDomains map + // if not found, sets sub1 as the default + String headerValue = allowedDomains.getOrDefault(request.getParameter("allowedDomain"), + allowedDomains.get("sub1")); + + // add the header with our trusted sub1.example.com or sub2.example.com domains. + response.addHeader("Access-Control-Allow-Origin", headerValue); + } + ``` + + For more information on `Access-Control-Allow-Origin` see: + https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin + severity: "ERROR" + metadata: + shortDescription: "Permissive cross-domain policy with untrusted domains" + cwe: "CWE-942" + category: "security" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + technology: + - "java" + security-severity: "Low" +- id: java_crypto_rule-BlowfishKeySize + languages: + - "java" + patterns: + - pattern-inside: | + $KEYGEN = javax.crypto.KeyGenerator.getInstance("Blowfish", ...); + ... + - pattern: $KEYGEN.init($KEY_SIZE) + - metavariable-comparison: + comparison: "int($KEY_SIZE) < 128" + metavariable: "$KEY_SIZE" + message: | + The Blowfish encryption algorithm was meant as a drop-in replacement for DES and was created in + 1993. Smaller key sizes may make the ciphertext vulnerable to [birthday + attacks](https://en.wikipedia.org/wiki/Birthday_attack). While no known attacks against + Blowfish + exist, it should never be used to encrypt files over 4GB in size. If possible consider + using AES as the instance of `KeyGenerator` instead of Blowfish. + + To remediate the small key size, pass a value such as 256 to the `KeyGenerator.init(keySize)` + method. + + Example setting a larger key size and changing to `KeyGenerator` to AES: + ``` + public static void aesKeyGenerator() throws java.security.NoSuchAlgorithmException { + // Use the AES algorithm for key generation + KeyGenerator keyGenerator = KeyGenerator.getInstance("AES"); + + // Set the key size here + keyGenerator.init(256); + + // get the raw bytes of the key + byte[] key = keyGenerator.generateKey().getEncoded(); + + // pass the key bytes to create a SecretKeySpec + SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES"); + } + ``` + + Example setting a larger key size for Blowfish: + ``` + public static void blowFishKeyGenerator() throws java.security.NoSuchAlgorithmException { + // Use the Blowfish algorithm for key generation + KeyGenerator keyGenerator = KeyGenerator.getInstance("Blowfish"); + + // Set the key size here + keyGenerator.init(256); + + // get the raw bytes of the key + byte[] key = keyGenerator.generateKey().getEncoded(); + + // pass the key bytes to create a SecretKeySpec + SecretKeySpec secretKeySpec = new SecretKeySpec(key, "Blowfish"); + } + ``` + + For more information on Java Cryptography see: + https://docs.oracle.com/en/java/javase/15/security/java-cryptography-architecture-jca-reference-guide.html + severity: "WARNING" + metadata: + category: "security" + shortDescription: "Inadequate encryption strength" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + cwe: "CWE-326" + technology: + - "java" + security-severity: "Medium" +- id: java_crypto_rule-CipherDESInsecure + languages: + - "java" + patterns: + - pattern-either: + - pattern: javax.crypto.Cipher.getInstance("$ALG", ...) + - pattern: | + $PROP = (java.util.Properties $P).getProperty(..., "$ALG"); + ... + javax.crypto.Cipher.getInstance($PROP, ...); + - metavariable-regex: + metavariable: $ALG + regex: "^DES(/|$)" + message: | + DES, TripleDES and RC2 are all considered broken or insecure cryptographic algorithms. + Newer algorithms apply message integrity to validate ciphertext has not been tampered + with. Consider using `ChaCha20Poly1305` instead as it is easier and faster than the + alternatives such as `AES-256-GCM`. + + For older applications that don't have support for `ChaCha20Poly1305`, + `AES-256-GCM` is recommended, however it has many drawbacks: + - Slower than `ChaCha20Poly1305`. + - Catastrophic failure if nonce values are reused. + + Example using `ChaCha20Poly1305`: + ``` + public encrypt() throws Exception { + chaChaEncryption("Secret text to encrypt".getBytes(StandardCharsets.UTF_8)); + } + + public SecureRandom getSecureRandomDRBG() throws NoSuchAlgorithmException { + // Use DRBG according to + http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-90Ar1.pdf + return SecureRandom.getInstance("DRBG", + // Security strength in bits (default is 128) + DrbgParameters.instantiation(256, + // Set prediction resistance and re-seeding + DrbgParameters.Capability.PR_AND_RESEED, + // Set the personalization string (optional, not necessary) + "some_personalization_string".getBytes() + ) + ); + } + + public Cipher getChaCha20Poly1305(int mode, byte[] ivKey, byte[] secretKey) throws + NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, + InvalidAlgorithmParameterException { + // Get a DRBG random number generator instance + SecureRandom random = getSecureRandomDRBG(); + // Create a ChaCha20-Poly1305 cipher instance + Cipher chaChaCipher = Cipher.getInstance("ChaCha20-Poly1305/None/NoPadding"); + // Create our parameterSpec using our ivKey + AlgorithmParameterSpec parameterSpec = new IvParameterSpec(ivKey); + // Create a SecretKeySpec using our secretKey + SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey, "ChaCha20"); + // Initialize and return the cipher for the provided mode + chaChaCipher.init(mode, secretKeySpec, parameterSpec, random); + return chaChaCipher; + } + + public void chaChaEncryption(byte[] plainText) throws NoSuchAlgorithmException, + NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException { + // Get a DRBG random number generator instance + SecureRandom random = getSecureRandomDRBG(); + // Create secretKey + byte[] secretKey = new byte[32]; + random.nextBytes(secretKey); + // Create an IV Key + byte[] ivKey = new byte[12]; + random.nextBytes(ivKey); + + // Create a chaCha encryption cipher instance + Cipher chaChaEncryptor = getChaCha20Poly1305(Cipher.ENCRYPT_MODE, ivKey, secretKey); + + // Encrypt the text using ChaCha20Poly1305 + byte[] cipherText = null; + try { + cipherText = chaChaEncryptor.doFinal(plainText); + } catch (IllegalBlockSizeException | BadPaddingException e) { + System.out.println("failed to encrypt text"); + return; + } + System.out.println("encrypted: " + Base64.getEncoder().encodeToString(cipherText)); + + // Create a chaCha decryption cipher instance + Cipher chaChaDecryptor = getChaCha20Poly1305(Cipher.DECRYPT_MODE, ivKey, secretKey); + + // Decrypt the text + byte[] decryptedText = null; + try { + decryptedText = chaChaDecryptor.doFinal(cipherText); + } catch (IllegalBlockSizeException | BadPaddingException e) { + System.out.println("failed to decrypt text"); + return; + } + System.out.println("decrypted: " + new String(decryptedText, StandardCharsets.UTF_8)); + } + ``` + + For more information on Java Cryptography see: + https://docs.oracle.com/en/java/javase/15/security/java-cryptography-architecture-jca-reference-guide.html + severity: "WARNING" + metadata: + shortDescription: "Inadequate encryption strength" + category: "security" + cwe: "CWE-326" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + technology: + - "java" + security-severity: "Medium" +- id: java_crypto_rule-CipherDESedeInsecure + languages: + - "java" + patterns: + - pattern-either: + - pattern: javax.crypto.Cipher.getInstance("$ALG", ...) + - pattern: | + $PROP = (java.util.Properties $P).getProperty(..., "$ALG"); + ... + javax.crypto.Cipher.getInstance($PROP, ...); + - metavariable-regex: + metavariable: $ALG + regex: "DESede(/|$)" + message: | + DES, TripleDES and RC2 are all considered broken or insecure cryptographic algorithms. + Newer algorithms apply message integrity to validate ciphertext has not been tampered + with. Consider using `ChaCha20Poly1305` instead as it is easier and faster than the + alternatives such as `AES-256-GCM`. + + For older applications that don't have support for `ChaCha20Poly1305`, + `AES-256-GCM` is recommended, however it has many drawbacks: + - Slower than `ChaCha20Poly1305`. + - Catastrophic failure if nonce values are reused. + + Example using `ChaCha20Poly1305`: + ``` + public encrypt() throws Exception { + chaChaEncryption("Secret text to encrypt".getBytes(StandardCharsets.UTF_8)); + } + + public SecureRandom getSecureRandomDRBG() throws NoSuchAlgorithmException { + // Use DRBG according to + http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-90Ar1.pdf + return SecureRandom.getInstance("DRBG", + // Security strength in bits (default is 128) + DrbgParameters.instantiation(256, + // Set prediction resistance and re-seeding + DrbgParameters.Capability.PR_AND_RESEED, + // Set the personalization string (optional, not necessary) + "some_personalization_string".getBytes() + ) + ); + } + + public Cipher getChaCha20Poly1305(int mode, byte[] nonceKey, byte[] secretKey) throws + NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, + InvalidAlgorithmParameterException { + // Get a DRBG random number generator instance + SecureRandom random = getSecureRandomDRBG(); + // Create a ChaCha20-Poly1305 cipher instance + Cipher chaChaCipher = Cipher.getInstance("ChaCha20-Poly1305/None/NoPadding"); + // Create our parameterSpec using our nonceKey + AlgorithmParameterSpec parameterSpec = new IvParameterSpec(nonceKey); + // Create a SecretKeySpec using our secretKey + SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey, "ChaCha20"); + // Initialize and return the cipher for the provided mode + chaChaCipher.init(mode, secretKeySpec, parameterSpec, random); + return chaChaCipher; + } + + public void chaChaEncryption(byte[] plainText) throws NoSuchAlgorithmException, + NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException { + // Get a DRBG random number generator instance + SecureRandom random = getSecureRandomDRBG(); + // Create secretKey + byte[] secretKey = new byte[32]; + random.nextBytes(secretKey); + // Create an IV nonceKey + byte[] nonceKey = new byte[12]; + random.nextBytes(nonceKey); + // Create a chaCha encryption cipher instance + Cipher chaChaEncryptor = getChaCha20Poly1305(Cipher.ENCRYPT_MODE, nonceKey, secretKey); + // Encrypt the text using ChaCha20Poly1305 + byte[] cipherText = null; + try { + cipherText = chaChaEncryptor.doFinal(plainText); + } catch (IllegalBlockSizeException | BadPaddingException e) { + System.out.println("failed to encrypt text"); + return; + } + System.out.println("encrypted: " + Base64.getEncoder().encodeToString(cipherText)); + // Create a chaCha decryption cipher instance + Cipher chaChaDecryptor = getChaCha20Poly1305(Cipher.DECRYPT_MODE, nonceKey, secretKey); + // Decrypt the text + byte[] decryptedText = null; + try { + decryptedText = chaChaDecryptor.doFinal(cipherText); + } catch (IllegalBlockSizeException | BadPaddingException e) { + System.out.println("failed to decrypt text"); + return; + } + System.out.println("decrypted: " + new String(decryptedText, StandardCharsets.UTF_8)); + } + ``` + + For more information on Java Cryptography see: + https://docs.oracle.com/en/java/javase/15/security/java-cryptography-architecture-jca-reference-guide.html + severity: "WARNING" + metadata: + shortDescription: "Use of a broken or risky cryptographic algorithm" + category: "security" + cwe: "CWE-327" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + technology: + - "java" + security-severity: "Medium" +- id: java_crypto_rule-CipherECBMode + languages: + - "java" + patterns: + - pattern-either: + - pattern: javax.crypto.Cipher.getInstance("$ALG", ...) + - pattern: | + $PROP = (java.util.Properties $P).getProperty(..., "$ALG"); + ... + javax.crypto.Cipher.getInstance($PROP, ...); + - metavariable-comparison: + metavariable: $ALG + comparison: | + $ALG in ( + "AES/ECB/NoPadding" "AES/ECB/PKCS5Padding" + "DES/ECB/NoPadding" "DES/ECB/PKCS5Padding" + "DESede/ECB/NoPadding" "DESede/ECB/PKCS5Padding" + "AES/ECB/PKCS7Padding" + ) + message: | + Cryptographic algorithms provide many different modes of operation, only some of which provide + message integrity. Without message integrity it could be possible for an adversary to attempt + to tamper with the ciphertext which could lead to compromising the encryption key. Newer + algorithms + apply message integrity to validate ciphertext has not been tampered with. + + Instead of using an algorithm that requires configuring a cipher mode, an algorithm + that has built-in message integrity should be used. Consider using `ChaCha20Poly1305` or + `AES-256-GCM` instead. + + For older applications that don't have support for `ChaCha20Poly1305`, `AES-256-GCM` is + recommended, however it has many drawbacks: + - Slower than `ChaCha20Poly1305`. + - Catastrophic failure if nonce values are reused. + + Example using `ChaCha20Poly1305`: + ``` + public encrypt() throws Exception { + chaChaEncryption("Secret text to encrypt".getBytes(StandardCharsets.UTF_8)); + } + + public SecureRandom getSecureRandomDRBG() throws NoSuchAlgorithmException { + // Use DRBG according to + http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-90Ar1.pdf + return SecureRandom.getInstance("DRBG", + // Security strength in bits (default is 128) + DrbgParameters.instantiation(256, + // Set prediction resistance and re-seeding + DrbgParameters.Capability.PR_AND_RESEED, + // Set the personalization string (optional, not necessary) + "some_personalization_string".getBytes() + ) + ); + } + + public Cipher getChaCha20Poly1305(int mode, byte[] ivKey, byte[] secretKey) throws + NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, + InvalidAlgorithmParameterException { + // Get a DRBG random number generator instance + SecureRandom random = getSecureRandomDRBG(); + // Create a ChaCha20-Poly1305 cipher instance + Cipher chaChaCipher = Cipher.getInstance("ChaCha20-Poly1305/None/NoPadding"); + // Create our parameterSpec using our ivKey + AlgorithmParameterSpec parameterSpec = new IvParameterSpec(ivKey); + // Create a SecretKeySpec using our secretKey + SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey, "ChaCha20"); + // Initialize and return the cipher for the provided mode + chaChaCipher.init(mode, secretKeySpec, parameterSpec, random); + return chaChaCipher; + } + + public void chaChaEncryption(byte[] plainText) throws NoSuchAlgorithmException, + NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException { + // Get a DRBG random number generator instance + SecureRandom random = getSecureRandomDRBG(); + // Create secretKey + byte[] secretKey = new byte[32]; + random.nextBytes(secretKey); + // Create an IV Key + byte[] ivKey = new byte[12]; + random.nextBytes(ivKey); + + // Create a chaCha encryption cipher instance + Cipher chaChaEncryptor = getChaCha20Poly1305(Cipher.ENCRYPT_MODE, ivKey, secretKey); + + // Encrypt the text using ChaCha20Poly1305 + byte[] cipherText = null; + try { + cipherText = chaChaEncryptor.doFinal(plainText); + } catch (IllegalBlockSizeException | BadPaddingException e) { + System.out.println("failed to encrypt text"); + return; + } + System.out.println("encrypted: " + Base64.getEncoder().encodeToString(cipherText)); + + // Create a chaCha decryption cipher instance + Cipher chaChaDecryptor = getChaCha20Poly1305(Cipher.DECRYPT_MODE, ivKey, secretKey); + + // Decrypt the text + byte[] decryptedText = null; + try { + decryptedText = chaChaDecryptor.doFinal(cipherText); + } catch (IllegalBlockSizeException | BadPaddingException e) { + System.out.println("failed to decrypt text"); + return; + } + System.out.println("decrypted: " + new String(decryptedText, StandardCharsets.UTF_8)); + } + ``` + + For more information on Java Cryptography see: + https://docs.oracle.com/en/java/javase/15/security/java-cryptography-architecture-jca-reference-guide.html + severity: "ERROR" + metadata: + shortDescription: "Use of a broken or risky cryptographic algorithm" + category: "security" + cwe: "CWE-327" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + technology: + - "java" + security-severity: "Medium" +- id: java_crypto_rule-CipherIntegrity + languages: + - "java" + patterns: + - pattern-either: + - pattern: javax.crypto.Cipher.getInstance("$ALG", ...) + - pattern: | + $PROP = (java.util.Properties $P).getProperty(..., "$ALG"); + ... + javax.crypto.Cipher.getInstance($PROP, ...); + - metavariable-comparison: + metavariable: $ALG + comparison: | + $ALG in ( + "AES" + "AES/CBC/NoPadding" "AES/CBC/PKCS5Padding" "AES/CBC/PKCS7Padding" + "AES/CFB/NoPadding" "AES/CFB/PKCS5Padding" "AES/CFB/PKCS7Padding" + "AES/CTR/NoPadding" + "AES/ECB/NoPadding" "AES/ECB/PKCS5Padding" "AES/ECB/PKCS7Padding" + "AES/OFB/NoPadding" "AES/OFB/PKCS5Padding" "AES/OFB/PKCS7Padding" + "ARCFOUR" + "DES" + "DES/CBC/NoPadding" "DES/CBC/PKCS5Padding" + "DES/ECB/NoPadding" "DES/ECB/PKCS5Padding" + "DESede" + "DESede/CBC/NoPadding" "DESede/CBC/PKCS5Padding" + "DESede/ECB/NoPadding" "DESede/ECB/PKCS5Padding" + "RC4" + ) + message: | + Cryptographic algorithms provide many different modes of operation, only some of which provide + message integrity. Without message integrity it could be possible for an adversary to attempt + to tamper with the ciphertext which could lead to compromising the encryption key. Newer + algorithms + apply message integrity to validate ciphertext has not been tampered with. + + Instead of using an algorithm that requires configuring a cipher mode, an algorithm + that has built-in message integrity should be used. Consider using `ChaCha20Poly1305` or + `AES-256-GCM` instead. + + For older applications that don't have support for `ChaCha20Poly1305`, `AES-256-GCM` is + recommended, however it has many drawbacks: + - Slower than `ChaCha20Poly1305`. + - Catastrophic failure if nonce values are reused. + + Example using `ChaCha20Poly1305`: + ``` + public encrypt() throws Exception { + chaChaEncryption("Secret text to encrypt".getBytes(StandardCharsets.UTF_8)); + } + + public SecureRandom getSecureRandomDRBG() throws NoSuchAlgorithmException { + // Use DRBG according to + http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-90Ar1.pdf + return SecureRandom.getInstance("DRBG", + // Security strength in bits (default is 128) + DrbgParameters.instantiation(256, + // Set prediction resistance and re-seeding + DrbgParameters.Capability.PR_AND_RESEED, + // Set the personalization string (optional, not necessary) + "some_personalization_string".getBytes() + ) + ); + } + + public Cipher getChaCha20Poly1305(int mode, byte[] ivKey, byte[] secretKey) throws + NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, + InvalidAlgorithmParameterException { + // Get a DRBG random number generator instance + SecureRandom random = getSecureRandomDRBG(); + // Create a ChaCha20-Poly1305 cipher instance + Cipher chaChaCipher = Cipher.getInstance("ChaCha20-Poly1305/None/NoPadding"); + // Create our parameterSpec using our ivKey + AlgorithmParameterSpec parameterSpec = new IvParameterSpec(ivKey); + // Create a SecretKeySpec using our secretKey + SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey, "ChaCha20"); + // Initialize and return the cipher for the provided mode + chaChaCipher.init(mode, secretKeySpec, parameterSpec, random); + return chaChaCipher; + } + + public void chaChaEncryption(byte[] plainText) throws NoSuchAlgorithmException, + NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException { + // Get a DRBG random number generator instance + SecureRandom random = getSecureRandomDRBG(); + // Create secretKey + byte[] secretKey = new byte[32]; + random.nextBytes(secretKey); + // Create an IV Key + byte[] ivKey = new byte[12]; + random.nextBytes(ivKey); + + // Create a chaCha encryption cipher instance + Cipher chaChaEncryptor = getChaCha20Poly1305(Cipher.ENCRYPT_MODE, ivKey, secretKey); + + // Encrypt the text using ChaCha20Poly1305 + byte[] cipherText = null; + try { + cipherText = chaChaEncryptor.doFinal(plainText); + } catch (IllegalBlockSizeException | BadPaddingException e) { + System.out.println("failed to encrypt text"); + return; + } + System.out.println("encrypted: " + Base64.getEncoder().encodeToString(cipherText)); + + // Create a chaCha decryption cipher instance + Cipher chaChaDecryptor = getChaCha20Poly1305(Cipher.DECRYPT_MODE, ivKey, secretKey); + + // Decrypt the text + byte[] decryptedText = null; + try { + decryptedText = chaChaDecryptor.doFinal(cipherText); + } catch (IllegalBlockSizeException | BadPaddingException e) { + System.out.println("failed to decrypt text"); + return; + } + System.out.println("decrypted: " + new String(decryptedText, StandardCharsets.UTF_8)); + } + ``` + + For more information on Java Cryptography see: + https://docs.oracle.com/en/java/javase/15/security/java-cryptography-architecture-jca-reference-guide.html + severity: "ERROR" + metadata: + shortDescription: "Use of a broken or risky cryptographic algorithm" + category: "security" + cwe: "CWE-327" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + technology: + - "java" + security-severity: "Medium" +- id: java_crypto_rule-CipherPaddingOracle + languages: + - "java" + patterns: + - pattern-either: + - pattern: javax.crypto.Cipher.getInstance("$ALG", ...) + - pattern: | + $PROP = (java.util.Properties $P).getProperty(..., "$ALG"); + ... + javax.crypto.Cipher.getInstance($PROP, ...); + - metavariable-comparison: + metavariable: $ALG + comparison: | + $ALG in ( + "AES/CBC/PKCS5Padding" "DES/CBC/PKCS5Padding" "DESede/CBC/PKCS5Padding" "AES/CBC/PKCS7Padding" + ) + message: | + Cryptographic block ciphers can be configured to pad individual blocks if there is not enough + input data to match the size of the block. This specific mode of CBC used in combination with + PKCS5Padding is susceptible to padding oracle attacks. An adversary could potentially decrypt + the message if the system exposed the difference between plaintext with invalid padding or + valid padding. The distinction between valid and invalid padding is usually revealed through + distinct error messages being returned for each condition. + + Consider switching to a more secure cipher that doesn't require padding and builds in message + authentication integrity directly into the algorithm. + + Consider using `ChaCha20Poly1305` or + `AES-256-GCM` instead. + + For older applications that don't have support for `ChaCha20Poly1305`, `AES-256-GCM` is + recommended, however it has many drawbacks: + - Slower than `ChaCha20Poly1305`. + - Catastrophic failure if nonce values are reused. + + Example using `ChaCha20Poly1305`: + ``` + public encrypt() throws Exception { + chaChaEncryption("Secret text to encrypt".getBytes(StandardCharsets.UTF_8)); + } + + public SecureRandom getSecureRandomDRBG() throws NoSuchAlgorithmException { + // Use DRBG according to + http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-90Ar1.pdf + return SecureRandom.getInstance("DRBG", + // Security strength in bits (default is 128) + DrbgParameters.instantiation(256, + // Set prediction resistance and re-seeding + DrbgParameters.Capability.PR_AND_RESEED, + // Set the personalization string (optional, not necessary) + "some_personalization_string".getBytes() + ) + ); + } + + public Cipher getChaCha20Poly1305(int mode, byte[] ivKey, byte[] secretKey) throws + NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, + InvalidAlgorithmParameterException { + // Get a DRBG random number generator instance + SecureRandom random = getSecureRandomDRBG(); + // Create a ChaCha20-Poly1305 cipher instance + Cipher chaChaCipher = Cipher.getInstance("ChaCha20-Poly1305/None/NoPadding"); + // Create our parameterSpec using our ivKey + AlgorithmParameterSpec parameterSpec = new IvParameterSpec(ivKey); + // Create a SecretKeySpec using our secretKey + SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey, "ChaCha20"); + // Initialize and return the cipher for the provided mode + chaChaCipher.init(mode, secretKeySpec, parameterSpec, random); + return chaChaCipher; + } + + public void chaChaEncryption(byte[] plainText) throws NoSuchAlgorithmException, + NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException { + // Get a DRBG random number generator instance + SecureRandom random = getSecureRandomDRBG(); + // Create secretKey + byte[] secretKey = new byte[32]; + random.nextBytes(secretKey); + // Create an IV Key + byte[] ivKey = new byte[12]; + random.nextBytes(ivKey); + + // Create a chaCha encryption cipher instance + Cipher chaChaEncryptor = getChaCha20Poly1305(Cipher.ENCRYPT_MODE, ivKey, secretKey); + + // Encrypt the text using ChaCha20Poly1305 + byte[] cipherText = null; + try { + cipherText = chaChaEncryptor.doFinal(plainText); + } catch (IllegalBlockSizeException | BadPaddingException e) { + System.out.println("failed to encrypt text"); + return; + } + System.out.println("encrypted: " + Base64.getEncoder().encodeToString(cipherText)); + + // Create a chaCha decryption cipher instance + Cipher chaChaDecryptor = getChaCha20Poly1305(Cipher.DECRYPT_MODE, ivKey, secretKey); + + // Decrypt the text + byte[] decryptedText = null; + try { + decryptedText = chaChaDecryptor.doFinal(cipherText); + } catch (IllegalBlockSizeException | BadPaddingException e) { + System.out.println("failed to decrypt text"); + return; + } + System.out.println("decrypted: " + new String(decryptedText, StandardCharsets.UTF_8)); + } + ``` + + For more information on padding oracle attacks see: + https://en.wikipedia.org/wiki/Padding_oracle_attack + + For more information on Java Cryptography see: + https://docs.oracle.com/en/java/javase/15/security/java-cryptography-architecture-jca-reference-guide.html + severity: "ERROR" + metadata: + shortDescription: "Use of a broken or risky cryptographic algorithm" + category: "security" + cwe: "CWE-327" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + technology: + - "java" + security-severity: "Medium" +- id: java_crypto_rule-CustomMessageDigest + languages: + - "java" + patterns: + - pattern: | + class $CLAZZ extends java.security.MessageDigest { + ... + } + message: | + The application was found implementing a custom `java.security.MessageDigest`. It is + strongly recommended that a standard Digest algorithm be chosen instead as implementing + a digest by hand is error-prone. The National Institute of Standards and + Technology (NIST) recommends the use of SHA-224, SHA-256, SHA-384, SHA-512, SHA-512/224, or + SHA-512/256. + + Example of creating a SHA-384 hash: + ``` + // Create a MessageDigest using the SHA-384 algorithm + MessageDigest sha384Digest = MessageDigest.getInstance("SHA-384"); + // Call update with your data + sha384Digest.update(input); + // Only call digest once all data has been fed into the update sha384digest instance + byte[] output = sha384Digest.digest(); + // output base64 encoded version of the hash + System.out.println("hash: " + Base64.getEncoder().encodeToString(output)); + ``` + severity: "WARNING" + metadata: + shortDescription: "Use of a broken or risky cryptographic algorithm" + category: "security" + cwe: "CWE-327" + owasp: + - "A6:2017-Security Misconfiguration" + - "A04:2021-Insecure Design" + technology: + - "java" + security-severity: "Medium" +- id: java_crypto_rule-HazelcastSymmetricEncryption + languages: + - "java" + patterns: + - pattern: "new com.hazelcast.config.SymmetricEncryptionConfig()" + message: | + The network communications for Hazelcast is configured to use a deprecated symmetric cipher. + Consider using TLS/SSL when establishing communications across the Hazelcast cluster. + + For more information on configuring TLS/SSL for Hazelcast see: + https://docs.hazelcast.com/imdg/4.2/security/tls-ssl + severity: "WARNING" + metadata: + shortDescription: "Inadequate encryption strength" + category: "security" + cwe: "CWE-326" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + technology: + - "java" + security-severity: "Medium" +- id: java_crypto_rule-InsufficientKeySizeRsa + languages: + - "java" + patterns: + - pattern-either: + - patterns: + - pattern-inside: | + $GEN = KeyPairGenerator.getInstance($ALG, ...); + ... + - pattern-either: + - pattern: "$VAR.initialize($SIZE, ...);" + - pattern: "new java.security.spec.RSAKeyGenParameterSpec($SIZE,...);" + - metavariable-comparison: + comparison: "$SIZE < 2048" + metavariable: "$SIZE" + - metavariable-regex: + metavariable: "$ALG" + regex: "\"(RSA|DSA)\"" + message: | + The application is generating an RSA key that is less than the recommended 2048 bits. + The National Institute of Standards and Technology (NIST) deprecated signing Digital + Certificates that contained RSA Public Keys of 1024 bits in December 2010. While + 1024-bit RSA keys have not been factored yet, advances in compute may make it possible + in the near future. + + Consider upgrading to the newer asymmetric algorithm such as `Ed25519` which handles + the complexities of generating key pairs and choosing correct key sizes for you: + ``` + public static KeyPair generateEd25519() throws NoSuchAlgorithmException { + // Choose Ed25519 for KeyPairGenerator Instance + KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("Ed25519"); + // Generate a KeyPair and return + return keyPairGenerator.generateKeyPair(); + } + ``` + + Otherwise use a key size greater than 2048 when generating RSA keys: + ``` + public static KeyPair generateRSA() throws NoSuchAlgorithmException { + // Choose RSA for KeyPairGenerator Instance + KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); + // Initialize with 2048 key size + keyPairGenerator.initialize(2048); + // Generate a KeyPair and return + return keyPairGenerator.generateKeyPair(); + } + ``` + + For more information on Ed25519 see: http://ed25519.cr.yp.to/ + + For more information on Java Cryptography see: + https://docs.oracle.com/en/java/javase/15/security/java-cryptography-architecture-jca-reference-guide.html + metadata: + shortDescription: "Inadequate encryption strength" + category: "security" + cwe: "CWE-326" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + security-severity: "Medium" + severity: "WARNING" +- id: java_crypto_rule-NullCipher + languages: + - "java" + pattern: "new javax.crypto.NullCipher()" + message: | + The application was found creating a `NullCipher` instance. `NullCipher` implements the + `Cipher` interface by returning ciphertext identical to the supplied plaintext. This means + any data passed to the `doFinal(...)` or `update(...)` methods will not actually encrypt + the input. + + Remove the NullCipher reference and replace with a legitimate `Cipher` instance such as + `ChaCha20-Poly1305` + + Example using `ChaCha20Poly1305`: + ``` + public encrypt() throws Exception { + chaChaEncryption("Secret text to encrypt".getBytes(StandardCharsets.UTF_8)); + } + + public SecureRandom getSecureRandomDRBG() throws NoSuchAlgorithmException { + // Use DRBG according to + http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-90Ar1.pdf + return SecureRandom.getInstance("DRBG", + // Security strength in bits (default is 128) + DrbgParameters.instantiation(256, + // Set prediction resistance and re-seeding + DrbgParameters.Capability.PR_AND_RESEED, + // Set the personalization string (optional, not necessary) + "some_personalization_string".getBytes() + ) + ); + } + + public Cipher getChaCha20Poly1305(int mode, byte[] ivKey, byte[] secretKey) throws + NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, + InvalidAlgorithmParameterException { + // Get a DRBG random number generator instance + SecureRandom random = getSecureRandomDRBG(); + // Create a ChaCha20-Poly1305 cipher instance + Cipher chaChaCipher = Cipher.getInstance("ChaCha20-Poly1305/None/NoPadding"); + // Create our parameterSpec using our ivKey + AlgorithmParameterSpec parameterSpec = new IvParameterSpec(ivKey); + // Create a SecretKeySpec using our secretKey + SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey, "ChaCha20"); + // Initialize and return the cipher for the provided mode + chaChaCipher.init(mode, secretKeySpec, parameterSpec, random); + return chaChaCipher; + } + + public void chaChaEncryption(byte[] plainText) throws NoSuchAlgorithmException, + NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException { + // Get a DRBG random number generator instance + SecureRandom random = getSecureRandomDRBG(); + // Create secretKey + byte[] secretKey = new byte[32]; + random.nextBytes(secretKey); + // Create an IV Key + byte[] ivKey = new byte[12]; + random.nextBytes(ivKey); + + // Create a chaCha encryption cipher instance + Cipher chaChaEncryptor = getChaCha20Poly1305(Cipher.ENCRYPT_MODE, ivKey, secretKey); + + // Encrypt the text using ChaCha20Poly1305 + byte[] cipherText = null; + try { + cipherText = chaChaEncryptor.doFinal(plainText); + } catch (IllegalBlockSizeException | BadPaddingException e) { + System.out.println("failed to encrypt text"); + return; + } + System.out.println("encrypted: " + Base64.getEncoder().encodeToString(cipherText)); + + // Create a chaCha decryption cipher instance + Cipher chaChaDecryptor = getChaCha20Poly1305(Cipher.DECRYPT_MODE, ivKey, secretKey); + + // Decrypt the text + byte[] decryptedText = null; + try { + decryptedText = chaChaDecryptor.doFinal(cipherText); + } catch (IllegalBlockSizeException | BadPaddingException e) { + System.out.println("failed to decrypt text"); + return; + } + System.out.println("decrypted: " + new String(decryptedText, StandardCharsets.UTF_8)); + } + ``` + + For more information on Java Cryptography see: + https://docs.oracle.com/en/java/javase/15/security/java-cryptography-architecture-jca-reference-guide.html + severity: "WARNING" + metadata: + shortDescription: "Use of a broken or risky cryptographic algorithm" + category: "security" + cwe: "CWE-327" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + technology: + - "java" + security-severity: "Medium" +- id: java_crypto_rule-RsaNoPadding + languages: + - "java" + patterns: + - pattern-either: + - pattern: javax.crypto.Cipher.getInstance("$ALG", ...) + - pattern: | + $PROP = (java.util.Properties $P).getProperty(..., "$ALG"); + ... + javax.crypto.Cipher.getInstance($PROP, ...); + - metavariable-regex: + metavariable: $ALG + regex: "(?i)^RSA/.*NoPadding$" + message: | + The software uses the RSA algorithm but does not incorporate Optimal Asymmetric + Encryption Padding (OAEP). By not enabling padding, the algorithm maybe vulnerable + to [chosen plaintext attacks](https://en.wikipedia.org/wiki/Chosen-plaintext_attack). + + To enable OAEP mode, pass `RSA/ECB/OAEPWithSHA-256AndMGF1Padding` to the `Cipher.getInstance` + method. + + Example encrypting and decrypting a message using RSA with OAEP: + ``` + public static void encryptWithRSA() throws InvalidKeyException, NoSuchAlgorithmException, + NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException { + // Generate an RSA Public and Private Key Pair + KeyPair keyPair = generateRSAKeys(); + // Create a Cipher instance using RSA, ECB with OAEP + Cipher rsaEncryptor = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding"); + // Initialize to ENCRYPT_MODE with the public key + rsaEncryptor.init(Cipher.ENCRYPT_MODE, keyPair.getPublic()); + // Encrypt our secret message + byte[] cipherText = rsaEncryptor.doFinal("Some secret + message".getBytes(StandardCharsets.UTF_8)); + + // Create a Cipher instance using RSA, ECB with OAEP + Cipher rsaDecryptor = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding"); + // Initialize to DECRYPT_MODE with the private key + rsaDecryptor.init(Cipher.DECRYPT_MODE, keyPair.getPrivate()); + // Decrypt the secret message + byte[] plainText = rsaDecryptor.doFinal(cipherText); + // Debug output + System.out.println(new String(plainText)); + } + ``` + More information on Optimal asymmetric encryption padding: + https://en.wikipedia.org/wiki/Optimal_asymmetric_encryption_padding + + For more information on Java Cryptography see: + https://docs.oracle.com/en/java/javase/15/security/java-cryptography-architecture-jca-reference-guide.html + metadata: + shortDescription: "Use of RSA algorithm without OAEP" + category: "security" + cwe: "CWE-780" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + security-severity: "Medium" + severity: "WARNING" +- id: java_crypto_rule-WeakMessageDigest + languages: + - "java" + patterns: + - pattern-either: + - pattern: java.security.MessageDigest.getInstance("$ALG", ...) + - pattern: java.security.Signature.getInstance("$ALG", ...) + - pattern: | + $PROP = (java.util.Properties $P).getProperty(..., "$ALG"); + ... + java.security.MessageDigest.getInstance("$ALG", ...); + - pattern: | + $PROP = (java.util.Properties $P).getProperty(..., "$ALG"); + ... + java.security.Signature.getInstance("$ALG", ...); + - metavariable-comparison: + metavariable: $ALG + comparison: | + $ALG in ( + "MD2" "MD4" "MD5" "MD5withRSA" + "SHA-1" "SHA1withRSA" "SHA1withDSA" + ) + message: | + The application was found using an insecure or risky digest or signature algorithm. Both MD5 + and SHA1 hash algorithms have been found to be vulnerable to producing collisions. + This means + that two different values, when hashed, can lead to the same hash value. If the application is + trying + to use these hash methods for storing passwords, then it is recommended to switch to a + password hashing + algorithm such as Argon2id or PBKDF2. + strongly recommended that a standard Digest algorithm be chosen instead as implementing + a digest by hand is error-prone. + + Example of creating a SHA-384 hash: + ``` + // Create a MessageDigest using the SHA-384 algorithm + MessageDigest sha384Digest = MessageDigest.getInstance("SHA-384"); + // Call update with your data + sha384Digest.update(input); + // Only call digest once all data has been fed into the update sha384digest instance + byte[] output = sha384Digest.digest(); + // output base64 encoded version of the hash + System.out.println("hash: " + Base64.getEncoder().encodeToString(output)); + ``` + + For more information on secure password storage see OWASP: + https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html + severity: "WARNING" + metadata: + shortDescription: "Use of a broken or risky cryptographic algorithm (SHA1/MD5)" + category: "security" + cwe: "CWE-327" + owasp: + - "A6:2017-Security Misconfiguration" + - "A04:2021-Insecure Design" + technology: + - "java" + security-severity: "Medium" +- id: java_crypto_rule-WeakTLSProtocol-DefaultHttpClient + languages: + - "java" + patterns: + - pattern: "new org.apache.http.impl.client.DefaultHttpClient();" + message: | + The `org.apache.http.impl.client.DefaultHttpClient` does not verify the hostnames upon connection. + + This allows for an adversary who is in between the application and the target host to intercept + potentially sensitive information or transmit malicious data. + + Do not use the `org.apache.http.impl.client.DefaultHttpClient();` as it is deprecated. Instead + use the new `java.net.http.HttpClient` that was introduced in Java 9. + + Example connecting to a host that will automatically do TLS validation: + ``` + // Create a new java.net.http.HttpClient + HttpClient httpClient = HttpClient.newHttpClient(); + // Create a HttpRequest builder + HttpRequest request = HttpRequest.newBuilder() + // Create a URI for a website which requires TLS + .uri(URI.create("https://www.example.com/")) + // Build the request + .build(); + + // Use the httpClient to send the request and use an HttpResponse.BodyHandlers String type + HttpResponse response = httpClient.send(request, HttpResponse.BodyHandlers.ofString()); + // Debug print + System.out.println(response); + ``` + metadata: + shortDescription: "Improper certificate validation" + category: "security" + cwe: "CWE-295" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + security-severity: "Medium" + severity: "WARNING" +- id: java_crypto_rule-WeakTLSProtocol-SSLContext + languages: + - "java" + patterns: + - pattern-either: + - pattern: javax.net.ssl.SSLContext.getInstance("$PROTO", ...) + - pattern: | + $PROP = (java.util.Properties $P).getProperty(..., "$PROTO"); + ... + javax.net.ssl.SSLContext.getInstance($PROP, ...); + - metavariable-comparison: + metavariable: $PROTO + comparison: | + $PROTO not in ("TLS" "TLSv1.2" "TLSv1.3" "DTLSv1.2" "DTLSv1.3") + message: | + Avoid initializing SSLContext with insecure protocols like `SSL`, `SSLv2`, or `SSLv3`. + These protocols are outdated and do not validate certificates by default. Additionally, + these older `SSL` versions have many known security issues. + + Instead, use secure protocols like `TLSv1.2` or `TLSv1.3`. + ``` + SSLContext context = SSLContext.getInstance("TLSv1.3"); + ``` + For more information on see OWASP: + - https://owasp.org/www-project-web-security-testing-guide/v41/4-Web_Application_Security_Testing/09-Testing_for_Weak_Cryptography/01-Testing_for_Weak_SSL_TLS_Ciphers_Insufficient_Transport_Layer_Protection + metadata: + shortDescription: "Improper certificate validation" + category: "security" + cwe: "CWE-295" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + security-severity: "MEDIUM" + severity: "WARNING" +- id: java_crypto_rule-WeakTLSProtocolVersion + languages: + - "java" + patterns: + - pattern-either: + - pattern-inside: | + import javax.net.ssl.*; + ... + - pattern-inside: | + import javax.net.ssl.SSLContext; + ... + - pattern-either: + - pattern-inside: | + SSLContext.getInstance("$UNSAFE_VERSION"); + - pattern-inside: | + SSLContext.getInstance(...); + ... + $ENGINE.setEnabledProtocols(new String[]{...,"$UNSAFE_VERSION",...}); + - pattern-not-inside: | + $C = SSLContext.getInstance(...); + ... + $ENGINE.setEnabledProtocols(new String[]{...,"TLSv1.2",...}); + - pattern-not-inside: | + $C = SSLContext.getInstance(...); + ... + $ENGINE.setEnabledProtocols(new String[]{...,"TLSv1.3",...}); + - pattern-not-inside: | + $C = SSLContext.getInstance(...); + ... + $ENGINE.setEnabledProtocols(new String[]{...,"DTLSv1.2",...}); + - pattern-not-inside: | + $C = SSLContext.getInstance(...); + ... + $ENGINE.setEnabledProtocols(new String[]{...,"DTLSv1.3",...}); + - metavariable-regex: + metavariable: "$UNSAFE_VERSION" + regex: "^(TLS|(D)?TLSv1.(0|1))$" + message: | + The application was found enabling insecure TLS protocol versions. When enabling protocol + versions for an `SSLContext`, only the following versions should be allowed: + - TLSv1.2 + - TLSv1.3 + - DTLSv1.2 + - DTLSv1.3 + + To mitigate potential security risks, it is strongly advised to enforce TLS 1.2 as the minimum + protocol version and disallow older versions such as TLS 1.0. Do note that newer versions of + Java do not even support TLS 1.0 and will throw `NoSuchAlgorithmException`. Versions of TLS + prior to 1.2 could expose the connection to downgrade attacks, where an adversary intercepts + the + connection and alters the requested protocol version to be a less secure one. + + In many scenarios, relying on the default system configuration does not meet compliance + standards. This is due to the application being deployed across diverse systems with varying + configurations and Java versions. While the default value may be secure on modern and + up-to-date systems, it may not hold true for older systems. Consequently, it is highly + recommended to explicitly define a secure configuration in all cases. + + Example configuring an SSLContext with TLSv1.2: + ``` + // Create an SSLContext with TLSv1.2 explicitly + SSLContext tlsContext = SSLContext.getInstance("TLSv1.2"); // or TLSv1.3, DTLSv1.2, DTLSv1.3 + + // Alternatively, set the enabled protocols + SSLContext serverSslContext = SSLContext.getInstance("TLS"); + SSLEngine serverEngine = serverSslContext.createSSLEngine(); + // Calling setEnabledProtocols will override the original context's configured protocol version + serverEngine.setEnabledProtocols(new String[]{ "TLSv1.2" }); + ``` + + For more information on `SSLContext` see: + - https://docs.oracle.com/en/java/javase/11/docs/api/java.base/javax/net/ssl/SSLContext.html + + For more information on MiTM attacks see: + - https://owasp.org/www-community/attacks/Manipulator-in-the-middle_attack + metadata: + shortDescription: "Inadequate encryption strength" + category: "security" + cwe: "CWE-326" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + security-severity: "Medium" + severity: "WARNING" +- id: java_endpoint_rule-HostnameVerifier + languages: + - "java" + message: | + The `HostnameVerifier` has been set to always return `true`. This effectively + disables the validation of server or client certificates. This could allow an + adversary who is in between the application and the target host to launch a Man + in the middle attack (MITM) i.e intercept potentially sensitive information or + inject malicious content into the communication stream. + + To mitigate this vulnerability and enhance the security of your application, it is + strongly advised to adhere to the default HostnameVerifier settings. This ensures + that the validation mechanism remains intact, providing a crucial layer of security + against unauthorized interception and data manipulation. + + Implementing the default HostnameVerifier can be achieved with the following code + snippet: + ``` + // Use the default HostnameVerifier + HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); + connection.setHostnameVerifier(HttpsURLConnection.getDefaultHostnameVerifier()); + ``` + For more information on TLS security, refer the following OWASP documentation: + https://cheatsheetseries.owasp.org/cheatsheets/Transport_Layer_Protection_Cheat_Sheet.html + metadata: + shortDescription: "Improper certificate validation" + category: "security" + cwe: "CWE-295" + owasp: + - "A6:2017-Security Misconfiguration" + - "A05:2021-Security Misconfiguration" + security-severity: "MEDIUM" + patterns: + - pattern-inside: | + class $V implements HostnameVerifier { + ... + } + - pattern-either: + - pattern: | + boolean verify(...) { + ... + return true; + ... + } + - pattern-not: + patterns: + - pattern: | + boolean verify(...) { + ... + return $VAR; + ... + } + - metavariable-regex: + metavariable: $VAR + regex: ^((?!true).)*$ + - pattern-not: | + boolean verify(...) { + $VAR = true; + ... + return $VAR; + ... + } + severity: "WARNING" +- id: java_endpoint_rule-UnvalidatedRedirect + languages: + - "java" + message: | + Unvalidated redirects occur when an application redirects a user to a + destination URL specified by a user supplied parameter that is not validated. + Such vulnerabilities can be used to facilitate phishing attacks. + + To avoid open redirect vulnerabilities in Java, one effective strategy is to + only allow redirection to URLs that are pre-defined in a safe list. This safe + list can be implemented using a collection like a Map, List, or Dictionary, + where you store all the valid URLs or URL patterns. When a redirect request is + made, you can check if the requested URL is in this safe list before proceeding + with the redirection. For example: + + ``` + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + private List safeUrls = new ArrayList<>(); + safeUrls.add("/home"); + safeUrls.add("/user/profile"); + safeUrls.add("/dashboard"); + + String redirectUrl = request.getParameter("url"); + + if (safeUrls.contains(redirectUrl)) { + response.sendRedirect(redirectUrl); + } else { + response.sendRedirect("/errorPage"); + } + }" + ``` + mode: "taint" + pattern-sources: + - patterns: + - pattern: | + $URL = ($X.servlet.http.HttpServletRequest $REQ).$M(...); + - metavariable-regex: + metavariable: "$M" + regex: "(getParameter|getCookies|getHeader|getHeaders|getHeaderNames|getPathInfo|getPathTranslated|getContextPath|getQueryString|getRemoteUser|getRequestedSessionId|getRequestURI|getRequestURL|getServletPath|getParts|getPart|getReader)" + pattern-sinks: + - pattern-either: + - pattern: | + ($X.servlet.http.HttpServletResponse $RES).sendRedirect($URL) + - pattern: | + ($X.servlet.http.HttpServletResponse $RES).addHeader("Location", $URL) + pattern-sanitizers: + - patterns: + - pattern-inside: | + if ($SAFE.contains($URL)){ + ... + } + - pattern-either: + - pattern: | + ($X.servlet.http.HttpServletResponse $RES).sendRedirect($URL) + - pattern: | + ($X.servlet.http.HttpServletResponse $RES).addHeader("Location", $URL) + metadata: + category: "security" + cwe: "CWE-601" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + shortDescription: "URL redirection to untrusted site ('Open Redirect')" + security-severity: "Info" + severity: "ERROR" +- id: java_endpoint_rule-X509TrustManager + languages: + - "java" + message: | + The `X509TrustManager` has been configured to return null. This effectively disables the + validation of server or client certificates. This could allow an adversary who is in + between the application and the target host to launch a Man in the middle attack (MITM) i.e + intercept potentially sensitive information or inject malicious content into the + communication stream. + + Consider using the + default `TrustManager` instead of implementing a custom one. If you must override + the default verification process, implement proper TrustManager verification for + `checkServerTrusted` and `checkClientTrusted` by throwing `CertificateException` if + the certificate is invalid. + + For most applications, using the default TrustManager provided by the Java runtime is + sufficient and recommended. Following is an example using the built in `TrustManagerFactory` + to manage validating certificate chains: + ``` + // Use the default TrustManagerFactory + TrustManagerFactory trustManagerFactory = + TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + // Use default system KeyStore, alternatively pass in your own keystore. + trustManagerFactory.init((KeyStore) null); + // Create SSLContext for TLS connections + SSLContext tlsContext = SSLContext.getInstance("TLS"); + // Initialize the tlsContext with our trust manager and a SecureRandom number generator. + tlsContext.init(null, trustManagerFactory.getTrustManagers(), new SecureRandom()); + ``` + For more information on TLS security, refer the following OWASP documentation: + https://cheatsheetseries.owasp.org/cheatsheets/Transport_Layer_Protection_Cheat_Sheet.html + metadata: + shortDescription: "Improper certificate validation" + category: "security" + cwe: "CWE-295" + owasp: + - "A6:2017-Security Misconfiguration" + - "A05:2021-Security Misconfiguration" + security-severity: "MEDIUM" + patterns: + - pattern-inside: | + class $V implements X509TrustManager { + ... + } + - pattern-either: + - pattern: "public void checkClientTrusted(...) {}" + - pattern: "public void checkServerTrusted(...) {}" + - patterns: + - pattern-either: + - pattern: | + X509Certificate[] getAcceptedIssuers() { + ... + return null; + ... + } + - pattern-not: + patterns: + - pattern: | + X509Certificate[] getAcceptedIssuers() { + ... + return $VAR; + ... + } + - metavariable-regex: + metavariable: $VAR + regex: ^((?!null).)*$ + - pattern-not: | + X509Certificate[] getAcceptedIssuers() { + $VAR = null; + ... + return $VAR; + ... + } + severity: "WARNING" +- id: java_file_rule-FileUploadFileName + languages: + - "java" + message: | + The filename provided by the FileUpload API can be tampered with + which could lead to unauthorized access or file inclusion vulnerabilities. + To mitigate this risk, it is essential to conduct rigorous validation of the + filenames provided by clients. This validation should ensure that the filename + adheres to a predefined structure, is devoid of potentially dangerous characters + (such as forward slashes / and backslashes \), and corresponds to an authorized + file only. + + For example, as a remediation strategy, the application could: + 1. Sanitize Filenames: Create a function to sanitize filenames by removing + or replacing unauthorized characters, including path traversal sequences (../ or ..\). + 2. Allowlist Validation: Implement a allowlist approach, allowing only filenames + that match a specific pattern or are part of a predefined list. + 3. Use Server-Generated Filenames: Rather than relying on client-provided filenames, + generate unique names server-side for storing files. + 4. Verify File Paths: Ensure files are being saved in the correct, + intended directory, and prevent redirection to unauthorized directories. + + Example remediation: + ``` + public class FileUploadHandler { + + protected void doPost(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + + Part filePart = request.getPart("file"); + String fileName = filePart.getSubmittedFileName(); + + // removes any path information from the filename + String sanitizedFileName = sanitizeFileName(fileName); + if (!isFileNameAllowed(sanitizedFileName)) { + throw new SecurityException("Invalid file name"); + } + + // Generate a unique file name for storage + String storedFileName = UUID.randomUUID().toString() + ".txt"; + + Path targetPath = Paths.get("uploads").resolve(storedFileName); + Files.copy(fileContent, targetPath, StandardCopyOption.REPLACE_EXISTING); + } + + private String sanitizeFileName(String fileName) { + return Paths.get(fileName).getFileName().toString(); + } + + private boolean isFileNameAllowed(String fileName) { + return fileName.matches("[a-zA-Z0-9._-]+"); + } + } + ``` + pattern-either: + - patterns: + - pattern-inside: | + $FILES = (ServletFileUpload $SFU).parseRequest(($X.servlet.http.HttpServletRequest $REQ)); + ... + for(FileItem $ITEM : $FILES) { + ... + } + - pattern: $ITEM.getName() + - pattern: ($X.servlet.http.Part $PART).getSubmittedFileName() + metadata: + shortDescription: "Improper limitation of a pathname to a restricted directory + ('Path Traversal')" + cwe: "CWE-22" + owasp: + - "A5:2017-Broken Access Control" + - "A01:2021-Broken Access Control" + security-severity: "Info" + category: "security" + technology: + - "java" + severity: "WARNING" +- id: java_file_rule-FilenameUtils + languages: + - "java" + message: | + The filename provided by the FileUpload API can be tampered with by the client to reference + unauthorized files. The provided filename should be properly validated to ensure it's properly + structured, contains no unauthorized path characters (e.g., / \), and refers to an authorized + file. + + The application was found to take a parameter from user input to construct a path name. If an + unfiltered parameter is passed to this file API, files from an arbitrary filesystem location + could be read. When data from an unstrusted source is untrusted source is used to construct + a file path, an attacker could potentially gain access to restrcited files locations outside + the relevant context. + + For example, if the application tries to access the users profile picture based on their user + name by concatenating the username to the filepath: + + "images/userprofiles/" + username + + The expected result of this would be "images/userprofiles/alice", however an attacker could + use a malicious input such as "../../../etc/passwd" to gain access to and/or manipulate + sensitive information + + Assume all input is malicious. Use an "accept known good" input validation strategy. + + Inputs can be sanitized by using the getName() method with concat() method to remove the + potentially malicious path traversal and limit the scope to a restricted directory. Or + input can also be sanitized by using resolve() method alongwith startsWith() method to + verify that the base path of the file is safe and expected. + + Example of limiting path traversal using getName: + + ``` + protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + + String input = req.getHeader("input"); + + input = getName(input); + + String safePath = concat(basePath, input); + + // Read the contents of the file + File file = new File(safePath); + } + ``` + metadata: + category: "security" + cwe: "CWE-22" + owasp: + - "A5:2017-Broken Access Control" + - "A01:2021-Broken Access Control" + shortDescription: "Improper limitation of a pathname to a restricted directory + ('Path Traversal')" + security-severity: "Info" + technology: + - "java" + mode: "taint" + pattern-sanitizers: + - pattern: | + $NAME = org.apache.commons.io.FilenameUtils.getName(...); + ... + $SAFE = concat($BASE, $NAME); + - pattern: | + $RET $FUN(...){ + ... + $PATH = $BP.resolve(...); + ... + if(!$PATH.startsWith(...)) { + throw new $EXC(...); + } + ... + } + pattern-sources: + - pattern: "(HttpServletRequest $REQ)" + pattern-sinks: + - pattern: "org.apache.commons.io.FilenameUtils.concat(...)" + - pattern: "org.apache.commons.io.FilenameUtils.getFullPath(...)" + - pattern: "org.apache.commons.io.FilenameUtils.getFullPathNoEndSeparator(...)" + - pattern: "org.apache.commons.io.FilenameUtils.getPath(...)" + - pattern: "org.apache.commons.io.FilenameUtils.getPathNoEndSeparator(...)" + - pattern: "org.apache.commons.io.FilenameUtils.normalize(...)" + - pattern: "org.apache.commons.io.FilenameUtils.normalizeNoEndSeparator(...)" + - pattern: "org.apache.commons.io.FilenameUtils.normalizeNoEndSeparator(...)" + - pattern: "org.apache.commons.io.FilenameUtils.removeExtension(...)" + - pattern: "org.apache.commons.io.FilenameUtils.separatorsToSystem(...)" + - pattern: "org.apache.commons.io.FilenameUtils.separatorsToUnix(...)" + - pattern: "org.apache.commons.io.FilenameUtils.separatorsToWindows(...)" + severity: "WARNING" +- id: java_inject_rule-CommandInjection + languages: + - java + mode: taint + pattern-sources: + - pattern: (javax.servlet.http.HttpServletRequest $R).$METHOD(...) + - pattern: (java.util.Scanner $S).$METHOD(...) + - pattern: (java.util.stream.Stream).$METHOD(...) + - pattern: (java.util.StringJoiner $SJ).toString(...) + - pattern: (java.sql.ResultSet.getString $R).$METHOD(...) + - pattern: (java.lang.System $S).getProperty(...) + - pattern: (java.lang.System $S).getenv(...) + - pattern: (java.lang.StringBuilder $SB).toString(...) + - pattern: (java.io.FileInputStream $F).read(...) + - pattern: (java.io.FileReader $F).read(...) + - pattern: (java.net.Socket $S).getInputStream(...) + - pattern: (java.net.Socket $S).getOutputStream(...) + - pattern: (java.net.DatagramSocket $S).receive(...) + - pattern: (java.net.DatagramSocket $S).getInputStream(...) + - pattern: java.nio.file.Files.readAllBytes(...) + - pattern: java.nio.file.Files.readAllLines(...) + - pattern: java.nio.file.Files.lines(...) + - pattern: java.nio.file.Files.newBufferedReader(...) + - pattern: org.apache.commons.io.IOUtils.toString(...) + - pattern: org.apache.commons.io.IOUtils.readLines(...) + - pattern: org.apache.commons.io.IOUtils.toByteArray(...) + - pattern: (com.fasterxml.jackson.databind.ObjectMapper $OM).readValue(...) + - pattern: (com.fasterxml.jackson.databind.ObjectMapper $OM).treeToValue(...) + - pattern: $CLASS.$METHOD(..., (javax.servlet.http.HttpServletRequest $R), ...) + - pattern: $FUNC(..., (javax.servlet.http.HttpServletRequest $R), ...) + - patterns: + - pattern-inside: + $FUNC(..., String $X, ...) { ... } + - focus-metavariable: $X + pattern-propagators: + - pattern: $LIST.add($X) + from: $X + to: $LIST + - pattern: $MAP.put(..., $X) + from: $X + to: $MAP + - pattern: $STR.concat($X) + from: $X + to: $STR + - pattern: $STR = String.format(..., $X, ...) + from: $X + to: $STR + - pattern: $STR = String.join(..., $X, ...) + from: $X + to: $STR + pattern-sinks: + - pattern: (ProcessBuilder $PB).command(...) + - pattern: new ProcessBuilder(...) + - pattern: (Runtime $R).exec(...) + message: | + OS command injection is a critical vulnerability that can lead to a full system + compromise as it may allow an adversary to pass in arbitrary commands or arguments + to be executed. + + User input should never be used in constructing commands or command arguments + to functions which execute OS commands. This includes filenames supplied by + user uploads or downloads. + + Ensure your application does not: + + - Use user-supplied information in the process name to execute. + - Use user-supplied information in an OS command execution function which does + not escape shell meta-characters. + - Use user-supplied information in arguments to OS commands. + + The application should have a hardcoded set of arguments that are to be passed + to OS commands. If filenames are being passed to these functions, it is + recommended that a hash of the filename be used instead, or some other unique + identifier. It is strongly recommended that a native library that implements + the same functionality be used instead of using OS system commands, due to the + risk of unknown attacks against third party commands. + + When specifying the OS command, ensure the application uses the full path + information, otherwise the OS may attempt to look up which process to execute + and could be vulnerable to untrusted search path vulnerabilities (CWE-426). + + Example of safely executing an OS command: + ``` + public static void executeCommand(String userFileData) throws java.io.IOException { + // Generate a random filename, do not use user input + String fileName = UUID.randomUUID().toString(); + // Create a Buffered/FileWriter + BufferedWriter writer = new BufferedWriter(new FileWriter(fileName)); + // Write the user content to our random file + writer.write(userFileData); + // Close the file to flush contents + writer.close(); + // Create the process builder with a hardcoded path to the binary, and our randomly + generated filename + ProcessBuilder processBuilder = new ProcessBuilder("/opt/app/path", fileName); + // Start the process + Process process = processBuilder.start(); + // Handle/redirect output of process here + // ... + } + ``` + + For more information on OS command injection, see OWASP's guide: + https://cheatsheetseries.owasp.org/cheatsheets/OS_Command_Injection_Defense_Cheat_Sheet.html + severity: "WARNING" + metadata: + shortDescription: "Improper neutralization of special elements used in an OS command + ('OS Command Injection')" + category: "security" + cwe: "CWE-78" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + technology: + - "java" + security-severity: "High" +- id: java_inject_rule-ELInjection + languages: + - "java" + message: | + This rule identifies potential Expression Language (EL) injection vulnerabilities within Java applications. + The rule targets use of `createValueExpression`, `createMethodExpression`, `ELProcessor.eval`, `getValue`, + and `setValue` methods, particularly when input to these methods is not a hardcoded string, indicating dynamic + evaluation of potentially untrusted input. + + `createValueExpression` creates a `ValueExpression` object which gets evaluated upon calling methods like + `getValue()` and `setValue()` or a Lambda `invoke()` i.e. it evaluates the expression passed to the + `createValueExpression` method. + + Similarly, `createMethodExpression` creates a `MethodExpression` object which gets evaluated upon calling + methods like `invoke()` and `getMethodInfo()`. + `ELProcessor.eval`, `getValue()`, and `setValue()` methods all evaluate their expressions which are passed + as parameters. + + Calling these method directly with user-supplied input may allow an adversary to execute arbitrary Java + code, including OS system commands. Never call these methods directly with user-supplied input. Consider + alternate methods such as a lookup table to take user input and resolve hardcoded values. + + Secure example: + + ``` + import javax.el.ELProcessor; + import java.util.Set; + + public class SafeELHandling { + private static final Set ALLOWED_VALUES = Set.of("value1", "value2", "value3"); + + public void processInput(String userInput) { + // Validate user input against the allowlist + if (!ALLOWED_VALUES.contains(userInput)) { + throw new IllegalArgumentException("Invalid input"); + } + + ELProcessor elProcessor = new ELProcessor(); + elProcessor.defineBean("userInput", userInput); + + // Example EL expression using the safe, predefined input + String result = (String) elProcessor.eval(userInput); + } + } + ``` + metadata: + category: "security" + cwe: "CWE-917" + shortDescription: "Improper neutralization of special elements used in an expression + language statement ('Expression Language Injection')" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + technology: + - "java" + security-severity: "Info" + pattern-either: + - patterns: + - pattern: | + (ExpressionFactory $EXP).createValueExpression((ELContext $CTX), $EXPR, + ...) + - pattern-not: | + (ExpressionFactory $EXP).createValueExpression((ELContext $CTX), "...", + ...) + - patterns: + - pattern: | + (ExpressionFactory $EXP).createMethodExpression((ELContext $CTX), $EXPR, + ...) + - pattern-not: | + (ExpressionFactory $EXP).createMethodExpression((ELContext $CTX), "...", + ...) + - patterns: + - pattern: | + ($X.el.ELProcessor $P).eval(...) + - pattern-not: | + ($X.el.ELProcessor $P).eval("...", ...) + - patterns: + - pattern: | + ($X.el.ELProcessor $P).getValue(...) + - pattern-not: | + ($X.el.ELProcessor $P).getValue("...", ...) + - patterns: + - pattern: | + ($X.el.ELProcessor $P).setValue(...) + - pattern-not: | + ($X.el.ELProcessor $P).setValue("...", "...") + severity: "WARNING" +- id: java_inject_rule-FileDisclosureRequestDispatcher + languages: + - "java" + mode: "taint" + pattern-sources: + - pattern: "(javax.servlet.http.HttpServletRequest $VAR).getParameter(...)" + - pattern: "(javax.servlet.http.HttpServletRequest $VAR).getParameterNames();" + - pattern: "(javax.servlet.http.HttpServletRequest $VAR).getParameterValues(...);" + - pattern: "(javax.servlet.http.HttpServletRequest $VAR).getParameterMap();" + - pattern: "(javax.servlet.http.HttpServletRequest $VAR).getHeader(...);" + - pattern: "(javax.servlet.http.HttpServletRequest $VAR).getPathInfo();" + pattern-sinks: + - patterns: + - pattern-not-inside: | + $VAL = $MAP.getOrDefault(..., "..."); + ... + - pattern-inside: | + $REQ = $HTTP.getRequestDispatcher(...); + ... + - pattern-either: + - pattern: "$REQ.include($FST, $SND)" + - pattern: "$REQ.forward($FST, $SND)" + message: | + The `HttpRequest.getRequestDispatcher()`'s `include` and `forward` methods will return + any file that is resolvable within the web application context. This includes the `web.xml` + file, any compiled classes, `jsp` files, and additional JAR or WAR libraries that are + accessible. + + Never pass user-supplied input directly to any of these methods. Use a lookup table or + hardcode + which views or paths the user should be directed to. Another option is to use a simple HTTP + redirect by returning an empty response body with a 301 status code and a `Location` redirect + header. In Java servlets, this can be done by using the `response.sendRedirect(...)` method. + + Example using a redirect instead of a `RequestDispatcher`: + ``` + // Create a look up table or pull from a data source + HashMap lookupTable = new HashMap<>(); + lookupTable.put("key1", "/Resource1"); + lookupTable.put("key2", "/Resource2"); + // Get user input + String userInput = request.getParameter("key"); + // Look up resource to redirect to from the user input + String redirectValue = lookupTable.getOrDefault(userInput, "/Resource1"); + // Redirect the user + response.sendRedirect(redirectValue); + ``` + metadata: + shortDescription: "Files or directories accessible to external parties" + category: "security" + cwe: "CWE-552" + owasp: + - "A5:2017-Broken Access Control" + - "A01:2021-Broken Access Control" + security-severity: "HIGH" + severity: "ERROR" +- id: java_inject_rule-FileDisclosureSpringFramework + languages: + - "java" + mode: "taint" + pattern-sources: + - pattern: "(javax.servlet.http.HttpServletRequest $VAR).getParameter(...)" + - pattern: "(javax.servlet.http.HttpServletRequest $VAR).getParameterNames();" + - pattern: "(javax.servlet.http.HttpServletRequest $VAR).getParameterValues(...);" + - pattern: "(javax.servlet.http.HttpServletRequest $VAR).getParameterMap();" + - pattern: "(javax.servlet.http.HttpServletRequest $VAR).getHeader(...);" + - pattern: "(javax.servlet.http.HttpServletRequest $VAR).getPathInfo();" + pattern-sinks: + - patterns: + - pattern-not-inside: | + $FST = $MAP.getOrDefault(..., "..."); + ... + - pattern: "new org.springframework.web.servlet.ModelAndView($FST, ...);" + - focus-metavariable: "$FST" + - patterns: + - pattern-not-inside: | + $FST = $MAP.getOrDefault(..., "..."); + ... + - pattern-inside: | + $MVC = new org.springframework.web.servlet.ModelAndView(); + ... + - pattern: "$MVC.setViewName(...);" + message: | + The `org.springframework.web.servlet.ModelAndView` class may + potentially allow access to restricted files if called with user-supplied input. + + The ModelAndView class looks up a view by name to resolve a `.jsp` + file. If this view name comes from user-supplied input, it could be abused to attempt + to return a JSP view that the user should not have access to. + + Use a lookup table or hardcode which views or paths the user should be directed to. + + Example using a lookup table to resolve a view from a Spring MVC application: + ``` + @RequestMapping(value="/mvc", method=RequestMethod.GET) + public ModelAndView mvc(HttpServletRequest request, HttpServletResponse response, Model model) + { + // Create a look up table or pull from a data source + HashMap lookupTable = new HashMap<>(); + lookupTable.put("key1", "view1"); + lookupTable.put("key2", "view2"); + // Get user input + String userInput = request.getParameter("key"); + // Look up view from the user input + String viewValue = lookupTable.getOrDefault(userInput, "Resource1"); + // return the new model and view + return new ModelAndView(viewValue); + } + ``` + + Example using a redirect instead of a `RequestDispatcher` in Spring: + ``` + @RequestMapping(value="/mvc", method=RequestMethod.GET) + public void mvc(HttpServletRequest request, HttpServletResponse response, Model model) + { + // Create a look up table or pull from a data source + HashMap lookupTable = new HashMap<>(); + lookupTable.put("key1", "view1"); + lookupTable.put("key2", "view2"); + // Get user input + String userInput = request.getParameter("key"); + // Look up resource to redirect to from the user input + String redirectValue = lookupTable.getOrDefault(userInput, "/Resource1"); + // return the new model and view + response.sendRedirect(redirectValue); + } + ``` + metadata: + shortDescription: "Files or directories accessible to external parties" + category: "security" + cwe: "CWE-552" + owasp: + - "A5:2017-Broken Access Control" + - "A01:2021-Broken Access Control" + security-severity: "HIGH" + severity: "ERROR" +- id: java_inject_rule-HttpParameterPollution + languages: + - "java" + mode: "taint" + pattern-sources: + - pattern: "(HttpServletRequest $REQ).getParameter(...)" + pattern-sanitizers: + - pattern: "java.net.URLEncoder.encode(...)" + - pattern: "com.google.common.net.UrlEscapers.urlPathSegmentEscaper().escape(...)" + pattern-sinks: + - pattern: "new org.apache.http.client.methods.HttpGet(...)" + - pattern: "new org.apache.commons.httpclient.methods.GetMethod(...)" + - pattern: "(org.apache.commons.httpclient.methods.GetMethod $GM).setQueryString(...)" + message: | + The application was found including unvalidated user input into a URL, which could lead to + HTTP Parameter Pollution (HPP) or worse, Server Side Request Forgery (SSRF). This could + allow an adversary to override the value of a URL or a request parameter. HTTP Parameter + Pollution + (HPP) attacks consist of injecting encoded query string delimiters into other existing + parameters. If a web + application does not properly sanitize the user input, an adversary may modify the logic of + these + requests to other applications. + + To remediate this issue, never allow user input directly into creation of a URL or URL + parameter. Consider + using a map to look up user-supplied information and return exact values to be used in the + generation of + requests. + + Example using a map to look up a key to be used in a HTTP request: + ``` + HashMap lookupTable = new HashMap<>(); + lookupTable.put("key1", "value1"); + lookupTable.put("key2", "value2"); + String userInput = request.getParameter("key"); + + // Create a CloseableHttpClient, ideally any requests issued should be done + // out-of-band from the servlet request itself (such as using a separate thread/scheduler + system) + try (final CloseableHttpClient httpClient = HttpClients.createDefault()) { + // Lookup the value from our user input from our lookupTable + String value = lookupTable.getOrDefault(userInput, "value1"); + // Construct the url, with the hardcoded url and only pass in the value from the + lookupTable, + // not direct user input + final HttpGet httpget = new HttpGet("https://example.com/getId?key="+value); + // Execute the request + CloseableHttpResponse clientResponse = httpClient.execute(httpget); + // Read the response + byte[] responseData = clientResponse.getEntity().getContent().readAllBytes(); + // Handle the response + // ... + } + ``` + + If using a map is not possible, the user-supplied input must be encoded prior to use, and + never allow full + URLs: + ``` + // Get user input + String userInput = request.getParameter("key"); + // Encode the string using java.net.URLEncoder with the UTF-8 character set + String encodedString = java.net.URLEncoder.encode(userInput, StandardCharsets.UTF_8); + // Create a CloseableHttpClient, ideally any requests issued should be done + // out-of-band from the servlet request itself (such as using a separate thread/scheduler + system) + try (final CloseableHttpClient httpClient = HttpClients.createDefault()) { + // Construct the url, with the hardcoded url and only pass in the encoded value, never a + full URL + final HttpGet httpget = new HttpGet("https://example.com/getId?key="+encodedString); + // Execute the request + CloseableHttpResponse clientResponse = httpClient.execute(httpget); + // Read the response + byte[] responseData = clientResponse.getEntity().getContent().readAllBytes(); + // handle the response + } + ``` + + For more information on SSRF see OWASP: + https://cheatsheetseries.owasp.org/cheatsheets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet.html + + For more information on HTTP Parameter Pollution see: + https://en.wikipedia.org/wiki/HTTP_parameter_pollution + severity: "ERROR" + metadata: + shortDescription: "Improper neutralization of argument delimiters in a command + ('Argument Injection')" + category: "security" + cwe: "CWE-88" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + technology: + - "java" + security-severity: "Medium" +- id: java_inject_rule-LDAPInjection + languages: + - "java" + mode: "taint" + pattern-sinks: + - pattern: "javax.naming.ldap.LdapName(...)" + - pattern: "(javax.naming.directory.Context $C).lookup(...)" + - pattern: "(javax.naming.Context $C).lookup(...)" + - patterns: + - pattern-inside: |- + (com.unboundid.ldap.sdk.LDAPConnection $C).search($QUERY, ...) + - pattern: "$QUERY" + - patterns: + - pattern-either: + - pattern: "$CTX.lookup(...)" + - patterns: + - pattern-inside: |- + $CTX.search($QUERY, ...) + - pattern: "$QUERY" + - patterns: + - pattern-inside: |- + $CTX.search($NAME, $FILTER, ...) + - pattern: "$FILTER" + - metavariable-pattern: + metavariable: "$CTX" + pattern-either: + - pattern: "(DirContext $C)" + - pattern: "(InitialDirContext $IDC)" + - pattern: "(LdapContext $LC)" + - pattern: "(EventDirContext $EDC)" + - pattern: "(LdapCtx $LC)" + - pattern: "(javax.naming.directory.DirContext $C)" + - pattern: "(javax.naming.directory.InitialDirContext $IDC)" + - pattern: "(javax.naming.ldap.LdapContext $LC)" + - pattern: "(javax.naming.event.EventDirContext $EDC)" + - pattern: "(com.sun.jndi.ldap.LdapCtx $LC)" + - patterns: + - pattern-either: + - patterns: + - pattern-inside: |- + $CTX.list($QUERY, ...) + - pattern: "$QUERY" + - patterns: + - pattern-inside: |- + $CTX.lookup($QUERY, ...) + - pattern: "$QUERY" + - patterns: + - pattern-inside: |- + $CTX.search($QUERY, ...) + - pattern: "$QUERY" + - patterns: + - pattern-inside: |- + $CTX.search($NAME, $FILTER, ...) + - pattern: "$FILTER" + - metavariable-pattern: + metavariable: "$CTX" + pattern-either: + - pattern: "(LdapTemplate $LT)" + - pattern: "(LdapOperations $LO)" + - pattern: "(org.springframework.ldap.core.LdapTemplate $LT)" + - pattern: "(org.springframework.ldap.core.LdapOperations $LO)" + pattern-sources: + - patterns: + - pattern-inside: | + $FUNC(..., $VAR, ...) { + ... + } + - pattern: "$VAR" + - patterns: + - pattern-inside: | + $FUNC(..., $X, ...) { + ... + $VAR = ... + $X; + ... + } + - pattern: "$VAR" + message: | + LDAP injection attacks exploit LDAP queries to influence how data is returned by + the LDAP server. + + Later versions of Java's `InitialDirContext.search` introduced a four argument method, one of + which is the `filterArg` parameter. The `filterArg` will be automatically encoded when + querying + the LDAP server. If this method signature is not available, the application must encode the + LDAP strings manually. + + More details on the four argument `search` method can be found here: + https://docs.oracle.com/en/java/javase/20/docs/api/java.naming/javax/naming/directory/InitialDirContext.html#search(javax.naming.Name,java.lang.String,java.lang.Object[],javax.naming.directory.SearchControls) + + To encode the string manually, it is recommended that all input passed to LDAP querying + systems + encode the following values: + + - Any occurrence of the null character must be escaped as “\00”. + - Any occurrence of the open parenthesis character must be escaped as “\28”. + - Any occurrence of the close parenthesis character must be escaped as “\29”. + - Any occurrence of the asterisk character must be escaped as “\2a”. + - Any occurrence of the backslash character must be escaped as “\5c”. + + Example function that safely encodes user-supplied input to be used in an LDAP query. + ``` + public static String encodeLDAPString(String input) { + // Note the \ character is replaced first + CharSequence[] chars = new CharSequence[] { "\\", "\0", "(", ")", "*" }; + CharSequence[] encoded = new CharSequence[] { "\\5c", "\\00", "\\28", "\\29", "\\2a" }; + // Iterate over each character sequence, replacing the raw value with an encoded version of + it + for (int i = 0; i < chars.length; i++) + { + // re-assign to input + input = input.replace(chars[i], encoded[i]); + } + // return our modified input string + return input; + } + ``` + + Example code that using the `filterArgs` parameter which automatically encodes for us: + ``` + // Create a properties to hold the ldap connection details + Properties props = new Properties(); + // Use the com.sun.jndi.ldap.LdapCtxFactory factory provider + props.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); + // The LDAP server URL + props.put(Context.PROVIDER_URL, "ldap://ldap.example.org:3889"); + // User details for the connection + props.put(Context.SECURITY_PRINCIPAL, "cn=admin,dc=example,dc=org"); + // LDAP account password + String ldapAccountPassword = getAccountPasswordFromSecureStoreOrKMS(); + // Pass in the LDAP password + props.put(Context.SECURITY_CREDENTIALS, ldapAccountPassword); + + // Create the LDAPContext + InitialDirContext ldapContext = new InitialDirContext(props); + // Example using SUBTREE_SCOPE SearchControls + SearchControls searchControls = new SearchControls(); + searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE); + + // Get user input for query + String userQuery = someUserInput; + // Use searchArguments to hold the user-supplied input + Object[] searchArguments = new Object[]{userQuery}; + // Hardcode the BaseDN, use the {0} format specifier to use the searchArguments array value, + and pass in the search controls. + // searchArguments automatically encode + NamingEnumeration answer = ldapContext.search("dc=example,dc=org", "(cn={0})", + searchArguments, searchControls); + // Process the response answer + while (answer.hasMoreElements()) { + ... + } + ``` + + For more information on LDAP Injection see OWASP: + https://cheatsheetseries.owasp.org/cheatsheets/LDAP_Injection_Prevention_Cheat_Sheet.html + severity: "WARNING" + metadata: + shortDescription: "Improper neutralization of special elements used in an LDAP + query ('LDAP Injection')" + category: "security" + cwe: "CWE-90" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + technology: + - "java" + security-severity: "Medium" +- id: java_inject_rule-OgnlInjection + languages: + - "java" + mode: "taint" + pattern-sources: + - patterns: + - pattern-inside: | + $FUNC(..., $VAR, ...) { + ... + } + - metavariable-pattern: + metavariable: "$VAR" + pattern-either: + - pattern: "(String $S)" + - pattern: "(Map $M)" + - pattern: "(Map $M)" + - pattern: "(Map $M)" + - pattern: "$VAR" + pattern-sinks: + - patterns: + - pattern-inside: |- + com.opensymphony.xwork2.util.TextParseUtil.translateVariables($VAL, ...) + - pattern: "$VAL" + - patterns: + - pattern-inside: |- + com.opensymphony.xwork2.util.TextParseUtil.translateVariablesCollection($VAL, ...) + - pattern: "$VAL" + - pattern: "com.opensymphony.xwork2.util.TextParseUtil.shallBeIncluded(...)" + - pattern: "com.opensymphony.xwork2.util.TextParseUtil.commaDelimitedStringToSet(...)" + - patterns: + - pattern-inside: |- + (com.opensymphony.xwork2.util.TextParser $P).evaluate($VAR, $VAL, ...) + - pattern: "$VAL" + - patterns: + - pattern-inside: |- + (com.opensymphony.xwork2.util.OgnlTextParser $P).evaluate($VAR, $VAL, ...) + - pattern: "$VAL" + - pattern: "(com.opensymphony.xwork2.ognl.OgnlReflectionProvider $P).getGetMethod($CLZ, + ...)" + - pattern: "(com.opensymphony.xwork2.ognl.OgnlReflectionProvider $P).getSetMethod($CLZ, + ...)" + - pattern: "(com.opensymphony.xwork2.ognl.OgnlReflectionProvider $P).getField($CLZ, + ...)" + - patterns: + - pattern-inside: |- + (com.opensymphony.xwork2.ognl.OgnlReflectionProvider $P).setProperties($MAP, ...) + - pattern: "$MAP" + - patterns: + - pattern-inside: |- + (com.opensymphony.xwork2.ognl.OgnlReflectionProvider $P).setProperty($VAL, ...) + - pattern: "$VAL" + - patterns: + - pattern-inside: |- + (com.opensymphony.xwork2.ognl.OgnlReflectionProvider $P).getValue($VAL, ...) + - pattern: "$VAL" + - patterns: + - pattern-inside: |- + (com.opensymphony.xwork2.ognl.OgnlReflectionProvider $P).setValue($VAL, ...) + - pattern: "$VAL" + - pattern: "(com.opensymphony.xwork2.util.reflection.ReflectionProvider $P).getGetMethod($CLZ, + ...)" + - pattern: "(com.opensymphony.xwork2.util.reflection.ReflectionProvider $P).getSetMethod($CLZ, + ...)" + - pattern: "(com.opensymphony.xwork2.util.reflection.ReflectionProvider $P).getField($CLZ, + ...)" + - patterns: + - pattern-inside: |- + (com.opensymphony.xwork2.util.reflection.ReflectionProvider $P).setProperties($MAP, ...) + - pattern: "$MAP" + - patterns: + - pattern-inside: |- + (com.opensymphony.xwork2.util.reflection.ReflectionProvider $P).setProperty($VAR, ...) + - pattern: "$VAR" + - patterns: + - pattern-inside: |- + (com.opensymphony.xwork2.util.reflection.ReflectionProvider $P).getValue($VAR, ...) + - pattern: "$VAR" + - patterns: + - pattern-inside: |- + (com.opensymphony.xwork2.util.reflection.ReflectionProvider $P).setValue($VAR, ...) + - pattern: "$VAR" + - patterns: + - pattern-inside: |- + (com.opensymphony.xwork2.ognl.OgnlUtil $P).setProperties($MAP, ...) + - pattern: "$MAP" + - patterns: + - pattern-inside: |- + (com.opensymphony.xwork2.ognl.OgnlUtil $P).setProperty($VAR, ...) + - pattern: "$VAR" + - patterns: + - pattern-inside: |- + (com.opensymphony.xwork2.ognl.OgnlUtil $P).getValue($VAR, ...) + - pattern: "$VAR" + - patterns: + - pattern-inside: |- + (com.opensymphony.xwork2.ognl.OgnlUtil $P).setValue($VAR, ...) + - pattern: "$VAR" + - patterns: + - pattern-inside: |- + (com.opensymphony.xwork2.ognl.OgnlUtil $P).callMethod($VAR, ...) + - pattern: "$VAR" + - patterns: + - pattern-inside: |- + (com.opensymphony.xwork2.ognl.OgnlUtil $P).compile($VAR, ...) + - pattern: "$VAR" + - pattern: "(org.apache.struts2.util.VelocityStrutsUtil $P).evaluate(...)" + - pattern: "org.apache.struts2.util.StrutsUtil.findString(...)" + - pattern: "org.apache.struts2.util.StrutsUtil.findValue(..., $VAL)" + - pattern: "org.apache.struts2.util.StrutsUtil.getText(...)" + - pattern: "org.apache.struts2.util.StrutsUtil.translateVariables(...)" + - patterns: + - pattern-inside: |- + org.apache.struts2.util.StrutsUtil.makeSelectList($VAR, ...) + - pattern: "$VAR" + - patterns: + - pattern-inside: |- + (org.apache.struts2.views.jsp.ui.OgnlTool $T).findValue($VAR, ...) + - pattern: "$VAR" + - pattern: "(com.opensymphony.xwork2.util.ValueStack $V).findString(...)" + - patterns: + - pattern-inside: |- + (com.opensymphony.xwork2.util.ValueStack $V).findValue($VAR, ...) + - pattern: "$VAR" + - patterns: + - pattern-inside: |- + (com.opensymphony.xwork2.util.ValueStack $V).setValue($VAR, ...) + - pattern: "$VAR" + - patterns: + - pattern-inside: |- + (com.opensymphony.xwork2.util.ValueStack $V).setParameter($VAR, ...) + - pattern: "$VAR" + message: | + The Object Graph Navigation Language (OGNL) is an expression language that allows access to + Java objects and properties stored in an ActionContext. Usage of these low-level + functions is discouraged because they can effectively execute strings as code, leading to + remote code execution vulnerabilities. Consider using struts tags when processing + user-supplied input and templates. + + Much like the Struts security guide recommending to not use raw `${}` EL expressions, + do not call or use the following OGNL packages with user-supplied input: + + - `com.opensymphony.xwork2.ognl` + - `com.opensymphony.xwork2.util` + - `com.opensymphony.xwork2.util.reflection` + - `org.apache.struts2.util.StrutsUtil` + + For more information on Struts2 security see: + https://struts.apache.org/security/#do-not-use-incoming-untrusted-user-input-in-forced-expression-evaluation + severity: "WARNING" + metadata: + shortDescription: "Expression injection (OGNL)" + category: "security" + cwe: "CWE-917" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + technology: + - "java" + security-severity: "High" +- id: java_inject_rule-SpotbugsPathTraversalAbsolute + languages: + - "java" + mode: "taint" + pattern-sources: + - pattern: (javax.servlet.http.HttpServletRequest $R).$METHOD(...) + - pattern: (java.util.Scanner $S).$METHOD(...) + - pattern: (java.util.stream.Stream).$METHOD(...) + - pattern: (java.util.StringJoiner $SJ).toString(...) + - pattern: (java.sql.ResultSet.getString $R).$METHOD(...) + - pattern: (java.lang.System $S).getProperty(...) + - pattern: (java.lang.System $S).getenv(...) + - pattern: (java.lang.StringBuilder $SB).toString(...) + - pattern: (java.io.FileInputStream $F).read(...) + - pattern: (java.io.FileReader $F).read(...) + - pattern: (java.net.Socket $S).getInputStream(...) + - pattern: (java.net.Socket $S).getOutputStream(...) + - pattern: (java.net.DatagramSocket $S).receive(...) + - pattern: (java.net.DatagramSocket $S).getInputStream(...) + - pattern: java.nio.file.Files.readAllBytes(...) + - pattern: java.nio.file.Files.readAllLines(...) + - pattern: java.nio.file.Files.lines(...) + - pattern: java.nio.file.Files.newBufferedReader(...) + - pattern: org.apache.commons.io.IOUtils.toString(...) + - pattern: org.apache.commons.io.IOUtils.readLines(...) + - pattern: org.apache.commons.io.IOUtils.toByteArray(...) + - pattern: (com.fasterxml.jackson.databind.ObjectMapper $OM).readValue(...) + - pattern: (com.fasterxml.jackson.databind.ObjectMapper $OM).treeToValue(...) + - pattern: $CLASS.$METHOD(..., (javax.servlet.http.HttpServletRequest $R), ...) + - pattern: $FUNC(..., (javax.servlet.http.HttpServletRequest $R), ...) + - patterns: + - pattern-inside: + $FUNC(..., @RequestParam String $X, ...) { ... } + - focus-metavariable: $X + pattern-propagators: + - pattern: $LIST.add($X) + from: $X + to: $LIST + - pattern: $MAP.put(..., $X) + from: $X + to: $MAP + - pattern: $STR.concat($X) + from: $X + to: $STR + - pattern: $STR = String.format(..., $X, ...) + from: $X + to: $STR + - pattern: $STR = String.join(..., $X, ...) + from: $X + to: $STR + pattern-sanitizers: + - pattern: "org.apache.commons.io.FilenameUtils.getName(...)" + pattern-sinks: + - patterns: + - pattern-inside: | + $U = new java.net.URI($VAR) + - pattern-either: + - pattern-inside: |- + new java.io.File($U) + - pattern-inside: |- + java.nio.file.Paths.get($U) + - pattern: "$VAR" + - patterns: + - pattern-inside: |- + new java.io.RandomAccessFile($INPUT,...) + - pattern: "$INPUT" + - pattern: "new java.io.FileReader(...)" + - pattern: "new javax.activation.FileDataSource(...)" + - pattern: "new java.io.FileInputStream(...)" + - pattern: "new java.io.FileOutputStream(...)" + - pattern: "new java.io.File(...)" + - pattern: "java.nio.file.Paths.get(...)" + - pattern: "java.io.File.createTempFile(...)" + - pattern: "java.io.File.createTempDirectory(...)" + - pattern: "java.nio.file.Files.createTempFile(...)" + - pattern: "java.nio.file.Files.createTempDirectory(...)" + - patterns: + - pattern: "$SRC.$METHOD(...)" + - metavariable-pattern: + metavariable: "$SRC" + pattern-either: + - pattern: "getClass()" + - pattern: "getClass().getClassLoader()" + - pattern: "(ClassLoader $C)" + - pattern: "(Class $C)" + - pattern: "$CLZ.getClassLoader()" + - metavariable-pattern: + metavariable: "$METHOD" + pattern-either: + - pattern: "getResourceAsStream" + - pattern: "getResource" + - patterns: + - pattern-inside: |- + new java.io.FileWriter($PATH, ...) + - pattern: "$PATH" + - patterns: + - pattern-inside: |- + new java.io.FileOutputStream($PATH, ...) + - pattern: "$PATH" + message: | + The application dynamically constructs file or path information. If the path + information comes from user input, it could be abused to read sensitive files, + access other users' data, or aid in exploitation to gain further system access. + + User input should never be used in constructing paths or files for interacting + with the filesystem. This includes filenames supplied by user uploads or downloads. + If possible, consider hashing user input or replacing it with unique values and + use `Path.resolve` to resolve and validate the path information + prior to processing any file functionality. + + Example using `Path.resolve` and not allowing direct user input: + ``` + // Class to store our user data along with a randomly generated file name + public static class UserData { + private String userFileNameUnsafe; + private String fileName; + public UserData(String userFileName) { + this.userFileNameUnsafe = userFileName; + // Generate a random ID for the filename + this.fileName = UUID.randomUUID().toString(); + } + public String getUserFileNameUnsafe() { return userFileNameUnsafe; }; + public String getFileName() { return fileName; }; + } + + public static void main(String[] args) throws Exception { + // User input, saved only as a reference + UserData userData = new UserData("..\\test.txt"); + // Restrict all file processing to this directory only + String base = "/var/app/restricted"; + Path basePath = Paths.get(base); + // Resolve the full path, but only use our random generated filename + Path fullPath = basePath.resolve(userData.getFileName()); + // verify the path is contained within our basePath + if (!fullPath.startsWith(base)) { + throw new Exception("Invalid path specified!"); + } + // process / work with file + } + ``` + + For more information on path traversal issues see OWASP: + https://owasp.org/www-community/attacks/Path_Traversal + metadata: + shortDescription: "Improper limitation of a pathname to a restricted directory + ('Path Traversal')" + cwe: "CWE-22" + owasp: + - "A5:2017-Broken Access Control" + - "A01:2021-Broken Access Control" + security-severity: "Medium" + technology: + - "java" + category: "security" + severity: "WARNING" +- id: java_ldap_rule-AnonymousLDAP + languages: + - "java" + patterns: + - pattern-inside: | + import javax.naming.Context; + ... + - pattern: "$ENV.put(Context.SECURITY_AUTHENTICATION, \"none\");" + message: | + The application does not provide authentication when communicating an LDAP + server. It is strongly recommended that the LDAP server be configured with + authentication and restrict what queries users can execute. + + Example code that authenticates with a remote LDAP server and encodes any + user-supplied input: + ``` + // Create a properties to hold the ldap connection details + Properties props = new Properties(); + // Use the com.sun.jndi.ldap.LdapCtxFactory factory provider + props.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); + // The LDAP server URL + props.put(Context.PROVIDER_URL, "ldap://ldap.example.org:3889"); + // User details for the connection + props.put(Context.SECURITY_PRINCIPAL, "cn=admin,dc=example,dc=org"); + // LDAP account password + String ldapAccountPassword = getAccountPasswordFromSecureStoreOrKMS(); + // Pass in the LDAP password + props.put(Context.SECURITY_CREDENTIALS, ldapAccountPassword); + + // Create the LDAPContext + InitialDirContext ldapContext = new InitialDirContext(props); + // Example using SUBTREE_SCOPE SearchControls + SearchControls searchControls = new SearchControls(); + searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE); + + // Get user input for query + String userQuery = someUserInput; + // Use searchArguments to hold the user-supplied input + Object[] searchArguments = new Object[]{userQuery}; + // Hardcode the BaseDN, use the {0} format specifier to use the searchArguments array value, + and pass in the search controls. + // searchArguments automatically encode + NamingEnumeration answer = ldapContext.search("dc=example,dc=org", "(cn={0})", + searchArguments, searchControls); + // Process the response answer + while (answer.hasMoreElements()) { + ... + } + ``` + + For information on enabling authentication, please see your LDAP server's + documentation. + + For more information on LDAP Injection see OWASP: + https://cheatsheetseries.owasp.org/cheatsheets/LDAP_Injection_Prevention_Cheat_Sheet.html + metadata: + shortDescription: "Missing authentication for critical function (LDAP)" + category: "security" + cwe: "CWE-306" + owasp: + - "A2:2017-Broken Authentication" + - "A07:2021-Identification and Authentication Failures" + security-severity: "High" + severity: "WARNING" +- id: java_password_rule-ConstantDBPassword + languages: + - "java" + patterns: + - pattern: "java.sql.DriverManager.getConnection($URI, $USR, \"...\");" + message: | + A potential hard-coded password was identified in a database connection string. + Passwords should not be stored directly in code + but loaded from secure locations such as a Key Management System (KMS). + + The purpose of using a Key Management System is so access can be audited and keys easily + rotated + in the event of a breach. By hardcoding passwords, it will be extremely difficult to determine + when or if, a key is compromised. + + The recommendation on which KMS to use depends on the environment the application is running + in: + + - For Google Cloud Platform consider [Cloud Key Management](https://cloud.google.com/kms/docs) + - For Amazon Web Services consider [AWS Key Management](https://aws.amazon.com/kms/) + - For on premise or other alternatives to cloud providers, consider [Hashicorp's + Vault](https://www.vaultproject.io/) + - For other cloud providers, please see their documentation + severity: "ERROR" + metadata: + shortDescription: "Use of hard-coded password" + category: "security" + cwe: "CWE-259" + owasp: + - "A2:2017-Broken Authentication" + - "A07:2021-Identification and Authentication Failures" + technology: + - "java" + security-severity: "Critical" + +- id: java_password_rule-EmptyDBPassword + languages: + - "java" + patterns: + - pattern: "java.sql.DriverManager.getConnection($URI, $USR, \"\");" + message: | + The application does not provide authentication when communicating a database + server. It is strongly recommended that the database server be configured with + authentication and restrict what queries users can execute. + + Please see your database server's documentation on how to configure a password. + + Additionally, passwords should not be stored directly in code + but loaded from secure locations such as a Key Management System (KMS). + + The purpose of using a Key Management System is so access can be audited and keys easily + rotated + in the event of a breach. By hardcoding passwords, it will be extremely difficult to determine + when or if, a key is compromised. + + The recommendation on which KMS to use depends on the environment the application is running + in: + + - For Google Cloud Platform consider [Cloud Key Management](https://cloud.google.com/kms/docs) + - For Amazon Web Services consider [AWS Key Management](https://aws.amazon.com/kms/) + - For on premise or other alternatives to cloud providers, consider [Hashicorp's + Vault](https://www.vaultproject.io/) + - For other cloud providers, please see their documentation + severity: "ERROR" + metadata: + shortDescription: "Missing authentication for critical function (database)" + category: "security" + cwe: "CWE-306" + owasp: + - "A2:2017-Broken Authentication" + - "A07:2021-Identification and Authentication Failures" + technology: + - "java" + security-severity: "Critical" +- id: java_password_rule-HardcodePassword + languages: + - "java" + pattern-either: + - pattern: "new java.security.KeyStore.PasswordProtection(\"...\".toCharArray())" + - pattern: "java.security.KeyStore.getInstance(...).load(..., \"...\".toCharArray())" + - pattern: "(java.security.KeyStore $KS).load(..., \"...\".toCharArray())" + - pattern: "KeyManagerFactory.getInstance(...).init(..., \"...\".toCharArray())" + - pattern: "(KeyManagerFactory $KMF).init(..., \"...\".toCharArray())" + - pattern: "PBEKeySpec(\"...\", ...)" + - pattern: "PasswordAuthentication(\"...\", \"...\")" + - pattern: "(PasswordCallback $CB).setPassword(\"...\")" + - pattern: "KerberosKey(...,\"...\",...)" + - pattern: "java.sql.DriverManager.getConnection(..., \"...\")" + - pattern: "io.vertx.ext.web.handler.CSRFHandler.create(..., \"...\")" + - pattern: "$S.setPassword(\"...\")" + message: | + A potential hard-coded password was identified in a hard-coded string. + Passwords should not be stored directly in code + but loaded from secure locations such as a Key Management System (KMS). + + The purpose of using a Key Management System is so access can be audited and keys easily + rotated + in the event of a breach. By hardcoding passwords, it will be extremely difficult to determine + when or if, a key is compromised. + + The recommendation on which KMS to use depends on the environment the application is running + in: + + - For Google Cloud Platform consider [Cloud Key Management](https://cloud.google.com/kms/docs) + - For Amazon Web Services consider [AWS Key Management](https://aws.amazon.com/kms/) + - For on premise or other alternatives to cloud providers, consider [Hashicorp's + Vault](https://www.vaultproject.io/) + - For other cloud providers, please see their documentation + severity: "ERROR" + metadata: + shortDescription: "Use of hard-coded password" + category: "security" + cwe: "CWE-259" + owasp: + - "A2:2017-Broken Authentication" + - "A07:2021-Identification and Authentication Failures" + technology: + - "java" + security-severity: "High" +- id: java_perm_rule-DangerousPermissions + pattern-either: + - pattern: | + $RUNVAR = new RuntimePermission("createClassLoader"); + ... + (PermissionCollection $PC).add($RUNVAR); + - pattern: | + $REFVAR = new ReflectPermission("suppressAccessChecks"); + ... + (PermissionCollection $PC).add($REFVAR); + - pattern: "(PermissionCollection $PC).add(new ReflectPermission(\"suppressAccessChecks\"))" + - pattern: "(PermissionCollection $PC).add(new RuntimePermission(\"createClassLoader\"))" + languages: + - "java" + message: | + The application was found to permit the `RuntimePermission` of `createClassLoader`, + `ReflectPermission` of `suppressAccessChecks`, or both. + + By granting the `RuntimePermission` of `createClassLoader`, a compromised application + could instantiate their own class loaders and load arbitrary classes. + + By granting the `ReflectPermission` of `suppressAccessChecks` an application will no longer + check Java language access checks on fields and methods of a class. This will effectively + grant access to protected and private members. + + For more information on `RuntimePermission` see: + https://docs.oracle.com/javase/8/docs/api/java/lang/RuntimePermission.html + + For more information on `ReflectPermission` see: + https://docs.oracle.com/javase/8/docs/api/java/lang/reflect/ReflectPermission.html + metadata: + shortDescription: "Incorrect permission assignment for critical resource" + category: "security" + cwe: "CWE-732" + owasp: + - "A5:2017-Broken Access Control" + - "A01:2021-Broken Access Control" + confidence: "HIGH" + security-severity: "Medium" + severity: "WARNING" +- id: java_perm_rule-OverlyPermissiveFilePermissionInline + languages: + - "java" + patterns: + - pattern-either: + - pattern: "java.nio.file.Files.setPosixFilePermissions(..., java.nio.file.attribute.PosixFilePermissions.fromString(\"$PERM_STRING\"));" + - pattern: | + $PERMISSIONS = java.nio.file.attribute.PosixFilePermissions.fromString("$PERM_STRING"); + ... + java.nio.file.Files.setPosixFilePermissions(..., $PERMISSIONS); + - metavariable-regex: + metavariable: "$PERM_STRING" + regex: "[rwx-]{6}[rwx]{1,}" + message: | + The application was found setting file permissions to overly permissive values. Consider + using the following values if the application user is the only process to access + the file: + + - `r--` - read only access to the file + - `w--` - write only access to the file + - `rw-` - read/write access to the file + + Example setting read/write permissions for only the owner of a `Path`: + ``` + // Get a reference to the path + Path path = Paths.get("/tmp/somefile"); + // Create a PosixFilePermission set from java.nio.file.attribute + Set permissions = + java.nio.file.attribute.PosixFilePermissions.fromString("rw-------"); + // Set the permissions + java.nio.file.Files.setPosixFilePermissions(path, permissions); + ``` + + For all other values please see: + https://en.wikipedia.org/wiki/File-system_permissions#Symbolic_notation + metadata: + shortDescription: "Incorrect permission assignment for critical resource" + cwe: "CWE-732" + owasp: + - "A5:2017-Broken Access Control" + - "A01:2021-Broken Access Control" + category: "security" + confidence: "HIGH" + security-severity: "Medium" + severity: "WARNING" +- id: java_script_rule-ScriptInjection + languages: + - "java" + mode: "taint" + pattern-sinks: + - patterns: + - pattern: "(javax.script.ScriptEngine $ENGINE).eval($ARG, ...);" + - pattern-not: "(javax.script.ScriptEngine $ENGINE).eval(\"...\");" + - pattern-not: "(javax.script.ScriptEngine $ENGINE).eval(\"...\", (javax.script.Bindings + $BINDING));" + - patterns: + - pattern-either: + - pattern: "(javax.script.Invocable $INVC).invokeFunction(..., $ARG)" + - pattern: "(javax.script.Invocable $INVC).invokeMethod(..., $ARG)" + pattern-sources: + - patterns: + - pattern-inside: |- + $FUNC(..., $VAR, ...) { ... } + - pattern: "$VAR" + message: | + The application executes an argument using a `ScriptEngine`'s `eval` method. This + may allow for direct OS commands to be executed as it's possible to pass in strings + such as `java.lang.Runtime.getRuntime().exec('/bin/sh ...');`. + + Never pass user-supplied input directly to the `eval` function. If possible hardcode all + JavasScript code or use a lookup table to resolve user input to known values. If none of these + techniques are possible, use `javax.script.Bindings` to pass input to the script engine. + + Example using `Binding` to safely pass in string values: + ``` + // Get ECMAScript engine + ScriptEngine engine = new ScriptEngineManager().getEngineByName("ECMAScript"); + + // User input, consisting of first and last name + String userFirstName = "John"; + String userLastName = "Snow"; + + // Create bindings to pass into our script, forcing the values to be String. + Bindings bindings = engine.createBindings(); + bindings.put("fname", new String(userFirstName)); + bindings.put("lname", new String(userLastName)); + + // Example script that concatenates a greeting with the user-supplied input first/last name + String script = "var greeting='Hello ';" + + // fname and lname variables will be resolved by our bindings defined above + "greeting += fname + ' ' + lname;" + + // prints greeting + "greeting"; + + try { + // Execute the script, passing in the bindings + Object bindingsResult = engine.eval(script, bindings); + // Work with result + // ... + } catch (ScriptException e) { + // Handle exception + e.printStackTrace(); + } + ``` + severity: "ERROR" + metadata: + shortDescription: "Improper control of generation of code ('Code Injection')" + category: "security" + cwe: "CWE-94" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "High" +- id: java_script_rule-SpringSpelExpressionParser + languages: + - "java" + patterns: + - pattern: "($PARSER $P).$METHOD($ARG);" + - pattern-not: "($PARSER $P).$METHOD(\"...\");" + - metavariable-pattern: + metavariable: "$PARSER" + pattern-either: + - pattern: "org.springframework.expression.spel.standard.SpelExpressionParser" + - pattern: "org.springframework.expression.ExpressionParser" + - metavariable-regex: + metavariable: "$METHOD" + regex: "(parseExpression|parseRaw)" + message: | + The application was found calling SpringFramework's `SpelExpressionParser.parseExpression`. + Calling this method directly with user-supplied input may allow an adversary to + execute arbitrary Java code including OS system commands. + + Never call `parseExpression` or `parseRaw` directly with user-supplied input. Consider + alternate + methods such as a lookup table to take user input and resolve hardcoded values. + + Later versions of SpringFramework introduced a `SimpleEvaluationContext` which can be + used to access bound data when calling the `getValue` result of `parseExpression`. This + `SimpleEvaluationContext` has a reduced set of functionality and can restrict data binding + to read-only or read-write contexts. An adversary could still access public properties + or fields on custom types that have been provided to the evaluation context. Use with caution. + + Example using `SimpleEvaluationContext` with a read-write data binding context: + ``` + @RequestMapping(value="/spel", method=RequestMethod.POST) + public String spel(@Validated User user, Model model) { + // Create the Expression Parser + SpelExpressionParser parser = new SpelExpressionParser(); + // Parse the expression + Expression parsedExpression = parser.parseExpression(model.getPossiblyUnsafeData()); + // Create the read-write data binding context + SimpleEvaluationContext context = SimpleEvaluationContext.forReadWriteDataBinding().build(); + // Execute the expression, passing in the read-write context + Object result = parsedExpression.getValue(context); + // work with the result + // ... + return "user"; + } + ``` + + For more information on SimpleEvaluationContext see: + https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/expression/spel/support/SimpleEvaluationContext.html + severity: "ERROR" + metadata: + shortDescription: "Improper neutralization of special elements used in an expression + language statement ('Expression Language Injection')" + category: "security" + cwe: "CWE-917" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "High" +- id: java_smtp_rule-InsecureSmtp + languages: + - "java" + patterns: + - pattern-either: + - pattern-inside: | + $E = new org.apache.commons.mail.SimpleEmail(...); + ... + - pattern-inside: | + $E = new org.apache.commons.mail.Email(...); + ... + - pattern-inside: | + $E = new org.apache.commons.mail.MultiPartEmail(...); + ... + - pattern-inside: | + $E = new org.apache.commons.mail.HtmlEmail(...); + ... + - pattern-inside: | + $E = new org.apache.commons.mail.ImageHtmlEmail(...); + ... + - pattern-not: | + $E.setSSLOnConnect(true); + ... + $E.setSSLCheckServerIdentity(true); + message: | + The Apache commons mail client by default does not enable TLS server identity. + This allows for an adversary who is in between the application and the target host to intercept + potentially sensitive information or transmit malicious data. + + Enable checking server identity by calling `Email.setSSLCheckServerIdentity(true)` + + Example email client that enables TLS and server identity: + ``` + // Create an email client + Email email = new SimpleEmail(); + // Configure the email hostname + email.setHostName("smtp.mail.example.com"); + // Set the port + email.setSmtpPort(465); + // Securely retrieve username and password values + String username = getUserNameFromKMSorSecretStore(); + String password = getPasswordFromKMSorSecretStore(); + // Configure the Authenticator + DefaultAuthenticator auth = new DefaultAuthenticator(username, password); + // Set the authenticator + email.setAuthenticator(auth); + // Ensure we use SSL on connect + email.setSSLOnConnect(true); + // Ensure we validate server identity + email.setSSLCheckServerIdentity(true); + // configure the rest of the email + email.setFrom("x@example.com"); + email.setSubject("TestMail"); + email.setMsg("This is a test mail ... :-)"); + email.addTo("y@example.com"); + email.send(); + ``` + metadata: + shortDescription: "Improper validation of certificate with host mismatch" + category: "security" + cwe: "CWE-297" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + security-severity: "Medium" + severity: "ERROR" +- id: java_smtp_rule-SmtpClient + languages: + - "java" + message: | + The application was found calling `MimeMessage` methods without encoding + new line characters. Much like HTTP, Simple Mail Transfer Protocol (SMTP) is a + text based protocol that uses headers to convey additional directives for how + email messages should be treated. An adversary could potentially cause email + messages to be sent to unintended recipients by abusing the CC or BCC headers + if they were able to inject them. + + To mitigate this issue, `\r\n` (CRLF) character sequences must be escaped + or encoded prior to being used in any of the `MimeMessage` methods. + + Example that escapes values that come from user input with + [Apache Commons Text](https://commons.apache.org/proper/commons-text/): + ``` + // Create a MimeMessage with a javax.mail.Session + Message message = new MimeMessage(session); + // Set the from address + message.setFrom(new InternetAddress("source@example.com")); + // Set the to address + message.setRecipients(Message.RecipientType.TO,new InternetAddress[] {new + InternetAddress("destination@example.com")}); + // Example user input + String subject = "potentially malicious data"; + String headerValue = "potentially malicious data"; + // Use Apache Commons Text StringEscapeUtils.escapeJava to encode \r\n to \\r\\n. + message.setSubject(StringEscapeUtils.escapeJava(subject)); + // Use Apache Commons Text StringEscapeUtils.escapeJava to encode \r\n to \\r\\n. + message.addHeader("HeaderName", StringEscapeUtils.escapeJava(header)); + // Use Apache Commons Text StringEscapeUtils.escapeJava to encode \r\n to \\r\\n. + message.setDescription(StringEscapeUtils.escapeJava("some description")); + // Use Apache Commons Text StringEscapeUtils.escapeJava to encode \r\n to \\r\\n. + message.setDisposition(StringEscapeUtils.escapeJava("some disposition")); + // Set the mail body text + message.setText("Some email content."); + // Send the message + ``` + patterns: + - pattern-inside: | + $M = new MimeMessage(...); + ... + - pattern-either: + - patterns: + - pattern-either: + - pattern: "$M.setSubject($VAR)" + - pattern: "$M.addHeader($ARG, $VAR)" + - pattern: "$M.addHeader($VAR, $ARG)" + - pattern: "$M.setDescription($VAR)" + - pattern: "$M.setDisposition($VAR)" + - metavariable-regex: + metavariable: $VAR + regex: "^[a-zA-Z_$][a-zA-Z0-9_$]*$" + - patterns: + - pattern-either: + - pattern: "$M.setSubject($OBJ.$GETTER(...))" + - pattern: "$M.setSubject($OBJ.$GETTER(...) + ...)" + - pattern: "$M.setSubject(... + $OBJ.$GETTER(...))" + - pattern: "$M.setSubject(... + $OBJ.$GETTER(...) + ...)" + - pattern: "$M.addHeader($ARG, $OBJ.$GETTER(...))" + - pattern: "$M.addHeader($ARG, $OBJ.$GETTER(...) + ...)" + - pattern: "$M.addHeader($ARG, ... + $OBJ.$GETTER(...))" + - pattern: "$M.addHeader($ARG, ... + $OBJ.$GETTER(...) + ...)" + - pattern: "$M.addHeader($OBJ.$GETTER(...), $ARG)" + - pattern: "$M.addHeader($OBJ.$GETTER(...) + ..., $ARG)" + - pattern: "$M.addHeader(... + $OBJ.$GETTER(...), $ARG)" + - pattern: "$M.addHeader(... + $OBJ.$GETTER(...) + ..., $ARG)" + - pattern: "$M.setDescription($OBJ.$GETTER(...))" + - pattern: "$M.setDisposition($OBJ.$GETTER(...) + ...)" + - pattern: "$M.setDisposition(... + $OBJ.$GETTER(...))" + - pattern: "$M.setDisposition(... + $OBJ.$GETTER(...) + ...)" + - metavariable-regex: + metavariable: $GETTER + regex: ^get + metadata: + shortDescription: "Improper neutralization of special elements used in a command" + category: "security" + cwe: "CWE-77" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "Low" + severity: "ERROR" +- id: java_ssrf_rule-SSRF + languages: + - "java" + message: | + Server-Side-Request-Forgery (SSRF) exploits backend systems that initiate requests to third + parties. + If user input is used in constructing or sending these requests, an attacker could supply + malicious + data to force the request to other systems or modify request data to cause unwanted actions. + + Ensure user input is not used directly in constructing URLs or URIs when initiating requests + to third party + systems from back end systems. Care must also be taken when constructing payloads using user + input. Where + possible restrict to known URIs or payloads. Consider using a server-side map where keys are + used to return + URLs such as `https://site/goto?key=1` where `{key: 1, url: 'http://some.url/', key: 2, url: + 'http://...'}`. + + If you must use user-supplied input for requesting URLs, it is strongly recommended that the + HTTP client + chosen allows you to customize and block certain IP ranges at the network level. By blocking + RFC 1918 + addresses or other network address ranges, you can limit the severity of a successful SSRF + attack. Care must + also be taken to block certain protocol or address formatting such as IPv6. + + If you cannot block address ranges at the client level, you may want to run the HTTP client + as a protected + user, or in a protected network where you can apply IP Table or firewall rules to block access + to dangerous + addresses. Finally, if none of the above protections are available, you could also run a + custom HTTP proxy + and force all requests through it to handle blocking dangerous addresses. + + Example using a map to look up a key to be used in a HTTP request: + ``` + HashMap lookupTable = new HashMap<>(); + lookupTable.put("key1", "https://example.com/"); + lookupTable.put("key2", "https://safeurl.com/"); + String userInput = request.getParameter("key"); + + // Create a CloseableHttpClient, ideally any requests issued should be done + // out-of-band from the servlet request itself (such as using a separate thread/scheduler + system) + try (final CloseableHttpClient httpClient = HttpClients.createDefault()) { + // Lookup the value from our user input from our lookupTable + String value = lookupTable.getOrDefault(userInput, "https://example.com/"); + // Construct the url, with the hardcoded url and only pass in the value from the + lookupTable, + // not direct user input + final HttpGet httpget = new HttpGet(value); + // Execute the request + CloseableHttpResponse clientResponse = httpClient.execute(httpget); + // Read the response + byte[] responseData = clientResponse.getEntity().getContent().readAllBytes(); + // Handle the response + // ... + } + ``` + + If using a map is not possible, the user-supplied input must be encoded prior to use, and + never allow full + URLs: + ``` + // Get user input + String userInput = request.getParameter("key"); + // Encode the string using java.net.URLEncoder with the UTF-8 character set + String encodedString = java.net.URLEncoder.encode(userInput, StandardCharsets.UTF_8); + // Create a CloseableHttpClient, ideally any requests issued should be done + // out-of-band from the servlet request itself (such as using a separate thread/scheduler + system) + try (final CloseableHttpClient httpClient = HttpClients.createDefault()) { + // Construct the url, with the hardcoded url and only pass in the encoded value, never a + full URL + final HttpGet httpget = new HttpGet("https://example.com/getId?key="+encodedString); + // Execute the request + CloseableHttpResponse clientResponse = httpClient.execute(httpget); + // Read the response + byte[] responseData = clientResponse.getEntity().getContent().readAllBytes(); + // handle the response + } + ``` + + For more information on SSRF see OWASP: + https://cheatsheetseries.owasp.org/cheatsheets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet.html + pattern-either: + - patterns: + - pattern-either: + - pattern-inside: | + import java.net.*; + ... + - pattern-inside: | + import java.net.URL; + ... + - pattern-inside: | + import java.net.URI; + ... + - pattern: "new $TYPE(...). ... .$FUNC" + - pattern-not: "new $TYPE(\"...\"). ... .$FUNC" + - metavariable-pattern: + metavariable: "$FUNC" + pattern-either: + - pattern: "connect" + - pattern: "GetContent" + - pattern: "openConnection" + - pattern: "openStream" + - pattern: "getContent" + - metavariable-pattern: + metavariable: "$TYPE" + pattern-either: + - pattern: "URL" + - pattern: "java.net.URL" + - pattern: "URI" + - pattern: "java.net.URI" + - patterns: + - pattern-either: + - pattern-inside: | + import java.net.*; + ... + - pattern-inside: | + import java.net.InetSocketAddress; + ... + - pattern: | + new InetSocketAddress(..., $PORT) + - pattern-not: | + new InetSocketAddress("...", $PORT) + metadata: + shortDescription: "Server-Side Request Forgery (SSRF)" + category: "security" + cwe: "CWE-918" + owasp: + - "A1:2017-Injection" + - "A10:2021-Server-Side Request Forgery" + security-severity: "Medium" + severity: "ERROR" +- id: java_strings_rule-BadHexConversion + languages: + - "java" + message: | + The application is using `Integer.toHexString` on a digest array buffer which + may lead to an incorrect version of values. + + Consider using the `java.util.HexFormat` object introduced in Java 17. For older Java applications + consider using the `javax.xml.bind.DatatypeConverter`. + + Example using `HexFormat` to create a human-readable string: + ``` + // Create a MessageDigest using the SHA-384 algorithm + MessageDigest sha384Digest = MessageDigest.getInstance("SHA-384"); + // Call update with your data + sha384Digest.update("some input".getBytes(StandardCharsets.UTF_8)); + // Only call digest once all data has been fed into the update sha384digest instance + byte[] output = sha384Digest.digest(); + // Create a JDK 17 HexFormat object + HexFormat hex = HexFormat.of(); + // Use formatHex on the byte array to create a string (note that alphabet characters are + lowercase) + String hexString = hex.formatHex(output); + ``` + + For more information on DatatypeConverter see: + https://docs.oracle.com/javase/9/docs/api/javax/xml/bind/DatatypeConverter.html#printHexBinary-byte:A- + patterns: + - pattern-inside: | + $B_ARR = (java.security.MessageDigest $MD).digest(...); + ... + - pattern-either: + - pattern: | + for(...) { + ... + $B = $B_ARR[...]; + ... + Integer.toHexString($B); + } + - pattern: | + for(...) { + ... + Integer.toHexString($B_ARR[...]); + } + - pattern: | + for(byte $B :$B_ARR) { + ... + Integer.toHexString($B); + } + - pattern: | + while(...) { + ... + Integer.toHexString($B_ARR[...]) + } + - pattern: | + do { + ... + Integer.toHexString($B_ARR[...]) + } while(...) + - pattern: | + while(...) { + ... + $B = $B_ARR[...]; + ... + Integer.toHexString($B); + } + - pattern: | + do { + ... + $B = $B_ARR[...]; + ... + Integer.toHexString($B); + } while(...) + metadata: + shortDescription: "Incorrect type conversion or cast" + cwe: "CWE-704" + category: "security" + confidence: "HIGH" + owasp: + - "A6:2017-Security Misconfiguration" + - "A05:2021-Security Misconfiguration" + security-severity: "Info" + severity: "WARNING" +- id: java_strings_rule-FormatStringManipulation + languages: + - "java" + patterns: + - pattern-either: + - patterns: + - pattern-inside: | + String $INPUT = (HttpServletRequest $REQ).getParameter(...); + ... + - pattern-inside: | + String $FORMAT_STR = ... + $INPUT; + ... + - patterns: + - pattern-inside: | + String $INPUT = (HttpServletRequest $REQ).getParameter(...); + ... + - pattern-inside: | + String $FORMAT_STR = ... + $INPUT + ...; + ... + - pattern-inside: | + String $FORMAT_STR = ... + (HttpServletRequest $REQ).getParameter(...) + ...; + ... + - pattern-inside: | + String $FORMAT_STR = ... + (HttpServletRequest $REQ).getParameter(...); + ... + - pattern-either: + - pattern: "String.format($FORMAT_STR, ...);" + - pattern: "String.format(java.util.Locale.$LOCALE, $FORMAT_STR, ...);" + - pattern: "(java.util.Formatter $F).format($FORMAT_STR, ...);" + - pattern: "(java.util.Formatter $F).format(java.util.Locale.$LOCALE, $FORMAT_STR, + ...);" + - pattern: "(java.io.PrintStream $F).printf($FORMAT_STR, ...);" + - pattern: "(java.io.PrintStream $F).printf(java.util.Locale.$LOCALE, $FORMAT_STR, + ...);" + - pattern: "(java.io.PrintStream $F).format($FORMAT_STR, ...);" + - pattern: "(java.io.PrintStream $F).format(java.util.Locale.$LOCALE, $FORMAT_STR, + ...);" + - pattern: "System.out.printf($FORMAT_STR, ...);" + - pattern: "System.out.printf(java.util.Locale.$LOCALE, $FORMAT_STR, ...);" + - pattern: "System.out.format($FORMAT_STR, ...);" + - pattern: "System.out.format(java.util.Locale.$LOCALE, $FORMAT_STR, ...);" + message: | + The application allows user input to control format string parameters. By passing invalid + format + string specifiers an adversary could cause the application to throw exceptions or possibly + leak + internal information depending on application logic. + + Never allow user-supplied input to be used to create a format string. Replace all format + string + arguments with hardcoded format strings containing the necessary specifiers. + + Example of using `String.format` safely: + ``` + // Get untrusted user input + String userInput = request.getParameter("someInput"); + // Ensure that user input is not included in the first argument to String.format + String.format("Hardcoded string expecting a string: %s", userInput); + // ... + ``` + metadata: + shortDescription: "Use of externally-controlled format string" + cwe: "CWE-134" + category: "security" + confidence: "HIGH" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "Medium" + severity: "ERROR" +- id: java_strings_rule-ModifyAfterValidation + languages: + - "java" + patterns: + - pattern: | + (java.util.regex.Pattern $Y).matcher($VAR); + ... + $VAR.$METHOD(...); + - metavariable-regex: + metavariable: "$METHOD" + regex: "(replace|replaceAll|replaceFirst|concat)" + message: |+ + The application was found matching a variable during a regular expression + pattern match, and then calling string modification functions after validation has occurred. + This is usually indicative of a poor input validation strategy as an adversary may attempt to + exploit the removal of characters. + + For example a common mistake in attempting to remove path characters to protect against path + traversal is to match '../' and then remove any matches. However, if an adversary were to + include in their input: '....//' then the `replace` method would replace the first `../` but + cause the leading `..` and trailing `/` to join into the final string of `../`, effectively + bypassing the check. + + To remediate this issue always perform string modifications before any validation of a string. + It is strongly recommended that strings be encoded instead of replaced or removed prior to + validation. + + + Example replaces `..` before validation. Do note this is still not a recommended method for + protecting against directory traversal, always use randomly generated IDs or filenames instead: + ``` + // This is ONLY for demonstration purpose, never use untrusted input + // in paths, always use randomly generated filenames or IDs. + String input = "test../....//dir"; + // Use replaceAll _not_ replace + input = input.replaceAll("\\.\\.", ""); + // Input would be test///dir at this point + // Create a pattern to match on + Pattern pattern = Pattern.compile("\\.\\."); + // Create a matcher + Matcher match = pattern.matcher(input); + // Call find to see if .. is still in our string + if (match.find()) { + throw new Exception(".. detected"); + } + // Use the input (but do not modify the string) + System.out.println(input + " safe"); + ``` + + For more information see Carnegie Mellon University's Secure Coding Guide: + https://wiki.sei.cmu.edu/confluence/display/java/IDS11-J.+Perform+any+string+modifications+before+validation + + metadata: + shortDescription: "Collapse of data into unsafe value" + category: "security" + cwe: "CWE-182" + confidence: "HIGH" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "Info" + severity: "WARNING" +- id: java_strings_rule-NormalizeAfterValidation + patterns: + - pattern: | + $Y = java.util.regex.Pattern.compile("[<>]"); + ... + $Y.matcher($VAR); + ... + java.text.Normalizer.normalize($VAR, ...); + languages: + - "java" + message: | + The application was found matching a variable during a regular expression + pattern match, and then calling a Unicode normalize function after validation has occurred. + This is usually indicative of a poor input validation strategy as an adversary may attempt to + exploit the normalization process. + + To remediate this issue, always perform Unicode normalization before any validation of a + string. + + Example of normalizing a string before validation: + ``` + // User input possibly containing malicious unicode + String userInput = "\uFE64" + "tag" + "\uFE65"; + // Normalize the input + userInput = Normalizer.normalize(userInput, Normalizer.Form.NFKC); + // Compile our regex pattern looking for < or > characters + Pattern pattern = Pattern.compile("[<>]"); + // Create a matcher from the userInput + Matcher matcher = pattern.matcher(userInput); + // See if the matcher matches + if (matcher.find()) { + // It did so throw an error + throw new Exception("found banned characters in input"); + } + ``` + + For more information see Carnegie Mellon University's Secure Coding Guide: + https://wiki.sei.cmu.edu/confluence/display/java/IDS01-J.+Normalize+strings+before+validating+them + metadata: + shortDescription: "Incorrect behavior order: validate before canonicalize" + category: "security" + cwe: "CWE-180" + confidence: "HIGH" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "Info" + severity: "WARNING" +- id: java_templateinjection_rule-TemplateInjection + languages: + - "java" + message: | + The application may allow control over a template string. Providing user input directly in the + template by + dynamically creating template strings may allow an adversary to execute arbitrary Java code, + including + OS system commands. + + For Velocity, never call `evaluate` with user-supplied input in the template string. Use a + `VelocityContext` + object instead to data-bind user-supplied information as it will be treated as an underlying + data type and not + template code. + + Example using Apache Velocity's `VelocityContext` and escape tools to pass in user-supplied + data to a template: + ``` + // Create a tool manager + ToolManager manager = new ToolManager(true); + // Create a context from the tool manager + Context context = manager.createContext(); + // For demonstration purposes, alternatively configure from a properties file + context.put("esc", new EscapeTool()); + // For demonstration purposes, create an output buffer + StringWriter stringWriter = new StringWriter(); + // Get userInput + String userInput = "potentially malicious data"; + // Use the context to pass in the userInput value + context.put("userInput", userInput); + // Pass in the context, the output buffer, a logtag (demo), and the template with userInput + // making sure to escape it if in the context of HTML. + Velocity.evaluate(context, stringWriter, "demo", "Hello $esc.html($userInput)"); + // Work with the output buffer + // ... + ``` + + For other templating engines, please see your framework's documentation. + pattern-either: + - patterns: + - pattern: "org.apache.velocity.app.Velocity.evaluate(..., $VAR)" + - pattern-not: "org.apache.velocity.app.Velocity.evaluate(..., \"...\")" + - patterns: + - pattern-not-inside: | + $C = (freemarker.template.Configuration $CFG).getTemplate("..."); + ... + - pattern-inside: | + $C = (freemarker.template.Configuration $CFG).getTemplate($IN); + ... + - pattern: "$C.process(...)" + - patterns: + - pattern-inside: | + import com.mitchellbosecke.pebble.PebbleEngine; + ... + - pattern-inside: | + $C = $T.getTemplate($IN); + ... + - pattern-not-inside: | + $C = $T.getTemplate("..."); + ... + - pattern: "$C.evaluate(...)" + metadata: + shortDescription: "Improper control of generation of code ('Code Injection')" + category: "security" + cwe: "CWE-94" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "High" + severity: "ERROR" +- id: java_unsafe_rule-ExternalConfigControl + languages: + - "java" + patterns: + - pattern: | + $TAINTED = (HttpServletRequest $REQ).getParameter(...); + ... + (java.sql.Connection $CONN).setCatalog($TAINTED); + message: | + The application was found using user-supplied input in a `java.sql.Connection`'s + `setCatalog` call. This could allow an adversary to supply a different database for the + lifetime of the connection. Allowing external control of system settings can disrupt service + or cause an application to behave in unexpected, and potentially malicious ways. Most likely + this would only cause an error by providing a nonexistent catalog name. + + It is recommended to not use user-supplied input when selecting the database for an + applications + database connection. + severity: "WARNING" + metadata: + shortDescription: "External control of system or configuration setting" + category: "security" + cwe: "CWE-15" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + technology: + - "java" + security-severity: "Low" +- id: java_xml_rule-SAMLIgnoreComments + languages: + - "java" + message: | + SAML parses attestations as an XML document. By processing XML comments, comment + fields can end up modifying the interpretation of input fields. This could allow + an adversary to insert an XML comment to break up the attestation's username + or other fields, allowing an attacker to bypass authorization or authentication checks. + + To remediate this issue, when using `org.opensaml.xml.parse.BasicParserPool` ensure + `setIgnoreComments(false)` is not called. + + The default value of `ignoreComments` is true, which is safe. + + Ref: + - https://javadoc.io/doc/org.opensaml/xmltooling/latest/org/opensaml/xml/parse/BasicParserPool.html#ignoreComments + + For more information on how this issue can be exploited see: + https://developer.okta.com/blog/2018/02/27/a-breakdown-of-the-new-saml-authentication-bypass-vulnerability + + For more information on SAML security see OWASP: + https://cheatsheetseries.owasp.org/cheatsheets/SAML_Security_Cheat_Sheet.html + metadata: + shortDescription: "Weak authentication" + cwe: "CWE-1390" + category: "security" + owasp: + - "A5:2017-Broken Access Control" + - "A01:2021-Broken Access Control" + security-severity: "Medium" + pattern: "(org.opensaml.xml.parse.BasicParserPool $POOL).setIgnoreComments(false);" + severity: "WARNING" +- id: java_xml_rule-XmlDecoder + languages: + - "java" + message: | + Deserialization attacks exploit the process of reading serialized data and turning it back + into an object. By constructing malicious objects and serializing them, an adversary may + attempt to: + + - Inject code that is executed upon object construction, which occurs during the + deserialization process. + - Exploit mass assignment by including fields that are not normally a part of the serialized + data but are read in during deserialization. + + Consider safer alternatives such as serializing data in the JSON format. Ensure any format + chosen allows + the application to specify exactly which object types are allowed to be deserialized. + Additionally, when + deserializing, never deserialize to base object types like `Object` and only cast to the exact + object + type that is expected. + + To protect against mass assignment, only allow deserialization of the specific fields that are + required. If this is not easily done, consider creating an intermediary type that + can be serialized with only the necessary fields exposed. + + Do note that `XMLEncoder` and `XMLDecoder` are not recommended. If the application must + use this serialization method, use a custom ClassLoader to prevent loading of arbitrary + classes: + ``` + XMLDecoder decoder = new XMLDecoder(inputStream, null, null, new ClassLoader() { + @Override + protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException { + if (!name.equals(NameOfBeanHere.class.getName()) && + !name.equals(XMLDecoder.class.getName())) { + throw new RuntimeException("Unauthorized deserialization attempt: " + name); + } + + return super.loadClass(name, resolve); + } + }); + ``` + + For more information on XML security see OWASP's guide: + https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#java + + For more details on deserialization attacks in general, see OWASP's guide: + https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html + + It should be noted that [tools exist](https://github.com/frohoff/ysoserial) to + automatically create + exploit code for these vulnerabilities. + metadata: + shortDescription: "Deserialization of untrusted data" + category: "security" + cwe: "CWE-502" + owasp: + - "A8:2017-Insecure Deserialization" + - "A08:2021-Software and Data Integrity Failures" + security-severity: "High" + patterns: + - pattern: | + (java.beans.XMLDecoder $D).readObject(); + - pattern-not: + pattern-either: + - patterns: + - pattern-inside: | + java.beans.XMLDecoder $DEC = new java.beans.XMLDecoder(..., $CL); + ... + - pattern: $DEC.readObject(); + - metavariable-pattern: + metavariable: $CL + patterns: + - pattern: | + new ClassLoader(){ + ... + $RET loadClass(String name, boolean resolve){ + if($X){ + throw ... + } + ... + } + ... + } + - metavariable-pattern: + metavariable: $X + pattern-either: + - pattern: | + !name.equals(...) + - pattern: | + !$LIST.contains(name) + - patterns: + - pattern-inside: | + ClassLoader $CLASS_LOADER = $CL; + ... + java.beans.XMLDecoder $DEC = new java.beans.XMLDecoder(..., $CLASS_LOADER); + ... + - pattern: $DEC.readObject(); + - metavariable-pattern: + metavariable: $CL + patterns: + - pattern: | + new ClassLoader(){ + ... + $RET loadClass(String name, boolean resolve){ + if($X){ + throw ... + } + ... + } + ... + } + - metavariable-pattern: + metavariable: $X + pattern-either: + - pattern: | + !name.equals(...) + - pattern: | + !$LIST.contains(name) + severity: "WARNING" +- id: java_xml_rule-XsltTransform + languages: + - "java" + mode: "taint" + pattern-sources: + - patterns: + - pattern-either: + - patterns: + - pattern-inside: | + $FUNC(...,String $VAR, ...) { + ... + } + - pattern-either: + - pattern: "new FileInputStream(<... $VAR ...>);" + - pattern: "getClass().getResourceAsStream(<... $VAR ...>)" + - patterns: + - pattern-inside: | + class $CLZ { + String $X = "..."; + ... + } + - pattern-inside: | + $FUNC(...,String $Y, ...) { + ... + } + - pattern-either: + - pattern: "new FileInputStream($X + $Y);" + - pattern: "getClass().getResourceAsStream($X + $Y)" + pattern-sinks: + - patterns: + - pattern-either: + - pattern-inside: |- + (javax.xml.transform.TransformerFactory $T).newTransformer($SRC, ...) + - pattern-inside: |- + (javax.xml.transform.Transformer $T).transform($SRC, ...) + - pattern: "$SRC" + message: | + The application performs XSLT translation with potentially malicious input. An adversary who + is able to influence the + loaded + XSL document could call XSL functions or exploit External XML Entity (XXE) attacks that allow + file + retrieval or force the parser to connect to arbitrary servers to exfiltrate files. It is + strongly + recommended that an alternative approach is used to work with XML data. + + For increased security, never process user-supplied XSL style sheets. If XSLT processing is + absolutely + necessary, ensure that `FEATURE_SECURE_PROCESSING` is enabled prior to processing the XSLT + file: + ``` + // Create a new TransformerFactory instance + TransformerFactory transformerFactory = TransformerFactory.newInstance(); + // Enable the FEATURE_SECURE_PROCESSING feature + transformerFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + // Read in the XML Source + Source xmlSource = new StreamSource(new FileInputStream("hardcoded.xml")); + // Read in the XSL template file + Source xslSource = new StreamSource(new FileInputStream("hardcoded.xsl")); + /// Create the transformer object to do the transformation + Transformer transformer = transformerFactory.newTransformer(xslSource); + // Create a Result object for output + Result result = new StreamResult(System.out); + // Execute the transformation process + transformer.transform(xmlSource, result); + ``` + + For more information on XML security see OWASP's guide: + https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#java + + For more information on the secure processing feature see: + - https://xml.apache.org/xalan-j/features.html#secureprocessing + metadata: + shortDescription: "XML injection (aka Blind XPath injection)" + category: "security" + cwe: "CWE-91" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "Medium" + severity: "WARNING" +- id: java_xss_rule-WicketXSS + languages: + - "java" + patterns: + - pattern-inside: | + import org.apache.wicket.$A; + ... + - pattern: | + $OBJ.setEscapeModelStrings(false); + message: | + The application is disabling Wicket's string escaping functionality by calling + `setEscapeModelStrings(false)`. + This could lead to Cross Site Scripting (XSS) if used with user-supplied input. XSS is an + attack which exploits + a web application or system to treat user input + as markup or script code. It is important to encode the data depending on the specific context + it + is used in. There are at least six context types: + + - Inside HTML tags `
context 1
` + - Inside attributes: `
` + - Inside event attributes `` + - Inside script blocks: `` + - Unsafe element HTML assignment: `element.innerHTML = "context 5"` + - Inside URLs: `link` + + Script blocks alone have multiple ways they need to be encoded. Extra care must be taken if + user input + is ever output inside of script tags. + + User input that is displayed within the application must be encoded, sanitized or validated + to ensure it cannot be treated as HTML or executed as JavaScript code. Care must also be + taken + to not mix server-side templating with client-side templating, as the server-side templating + will + not encode things like {{ 7*7 }} which may execute client-side templating features. + + It is _NOT_ advised to encode user input prior to inserting into a data store. The data will + need to be + encoded depending on context of where it is output. It is much safer to force the displaying + system to + handle the encoding and not attempt to guess how it should be encoded. + + Use Wicket's built in escaping feature by calling `Component.setEscapeModelStrings(true);` + + For more information on Wicket components see: + - https://nightlies.apache.org/wicket/apidocs/9.x/org/apache/wicket/Component.html + + For more information on XSS see OWASP: + - https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html + metadata: + shortDescription: "Improper neutralization of input during web page generation + ('Cross-site Scripting')" + category: "security" + cwe: "CWE-79" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "Medium" + severity: "WARNING" +- id: java_xss_rule-XSSReqParamToServletWriter + languages: + - "java" + mode: "taint" + pattern-sources: + - pattern: (javax.servlet.http.HttpServletRequest $R).$METHOD(...) + - pattern: (java.util.Scanner $S).$METHOD(...) + - pattern: (java.util.stream.Stream).$METHOD(...) + - pattern: (java.util.StringJoiner $SJ).toString(...) + - pattern: (java.sql.ResultSet.getString $R).$METHOD(...) + - pattern: (java.lang.System $S).getProperty(...) + - pattern: (java.lang.System $S).getenv(...) + - pattern: (java.lang.StringBuilder $SB).toString(...) + - pattern: (java.io.FileInputStream $F).read(...) + - pattern: (java.io.FileReader $F).read(...) + - pattern: (java.net.Socket $S).getInputStream(...) + - pattern: (java.net.Socket $S).getOutputStream(...) + - pattern: (java.net.DatagramSocket $S).receive(...) + - pattern: (java.net.DatagramSocket $S).getInputStream(...) + - pattern: java.nio.file.Files.readAllBytes(...) + - pattern: java.nio.file.Files.readAllLines(...) + - pattern: java.nio.file.Files.lines(...) + - pattern: java.nio.file.Files.newBufferedReader(...) + - pattern: org.apache.commons.io.IOUtils.toString(...) + - pattern: org.apache.commons.io.IOUtils.readLines(...) + - pattern: org.apache.commons.io.IOUtils.toByteArray(...) + - pattern: (com.fasterxml.jackson.databind.ObjectMapper $OM).readValue(...) + - pattern: (com.fasterxml.jackson.databind.ObjectMapper $OM).treeToValue(...) + - pattern: $CLASS.$METHOD(..., (javax.servlet.http.HttpServletRequest $R), ...) + - pattern: $FUNC(..., (javax.servlet.http.HttpServletRequest $R), ...) + - patterns: + - pattern-inside: + $FUNC(..., String $X, ...) { ... } + - focus-metavariable: $X + pattern-propagators: + - pattern: $LIST.add($X) + from: $X + to: $LIST + - pattern: $MAP.put(..., $X) + from: $X + to: $MAP + - pattern: $STR.concat($X) + from: $X + to: $STR + - pattern: $STR = String.format(..., $X, ...) + from: $X + to: $STR + - pattern: $STR = String.join(..., $X, ...) + from: $X + to: $STR + pattern-sanitizers: + - pattern: org.owasp.encoder.Encode.forHtml(...) + - pattern: org.owasp.esapi.ESAPI.encoder().encodeForHTML(...) + - pattern: org.apache.commons.text.StringEscapeUtils.escapeHtml3(...) + - pattern: org.apache.commons.text.StringEscapeUtils.escapeHtml4(...) + - pattern: org.owasp.benchmark.helpers.Utils.encodeForHTML(...) + pattern-sinks: + - pattern: (javax.servlet.http.HttpServletResponse $R).getWriter().print(...) + - patterns: + - pattern-inside: | + $W = (javax.servlet.http.HttpServletResponse $R).getWriter(); + ... + - pattern: $W.print(...); + - pattern: (javax.servlet.http.HttpServletResponse $R).getWriter().println(...) + - patterns: + - pattern-inside: | + $W = (javax.servlet.http.HttpServletResponse $R).getWriter(); + ... + - pattern: $W.println(...); + - pattern: (javax.servlet.http.HttpServletResponse $R).getWriter().format(...) + - patterns: + - pattern-inside: | + $W = (javax.servlet.http.HttpServletResponse $R).getWriter(); + ... + - pattern: $W.format(...); + - pattern: (javax.servlet.http.HttpServletResponse $R).getWriter().append(...) + - patterns: + - pattern-inside: | + $W = (javax.servlet.http.HttpServletResponse $R).getWriter(); + ... + - pattern: $W.append(...); + - pattern: (javax.servlet.http.HttpServletResponse $R).getWriter().write(...) + - patterns: + - pattern-inside: | + $W = (javax.servlet.http.HttpServletResponse $R).getWriter(); + ... + - pattern: $W.write(...); + message: | + The application is returning user-supplied data from an HTTP request directly into an HTTP + response output + writer. This could lead to Cross Site Scripting (XSS) if the input were malicious + script code and the application server is not properly validating the output. + + XSS is an attack which exploits a web application or system to treat user input + as markup or script code. It is important to encode the data depending on the specific context + it is used in. There are at least six context types: + + - Inside HTML tags `
context 1
` + - Inside attributes: `
` + - Inside event attributes `` + - Inside script blocks: `` + - Unsafe element HTML assignment: `element.innerHTML = "context 5"` + - Inside URLs: `link` + + Script blocks alone have multiple ways they need to be encoded. Extra care must be taken if + user input + is ever output inside of script tags. + + User input that is displayed within the application must be encoded, sanitized or validated + to ensure it cannot be treated as HTML or executed as Javascript code. Care must also be + taken + to not mix server-side templating with client-side templating, as the server-side templating + will + not encode things like {{ 7*7 }} which may execute client-side templating features. + + It is _NOT_ advised to encode user input prior to inserting into a data store. The data will + need to be + encoded depending on context of where it is output. It is much safer to force the displaying + system to + handle the encoding and not attempt to guess how it should be encoded. + + If possible do not use user input directly in the output to the response writer. + + If the application must output user-supplied input, it will need to encode the data depending + on + the output context. + + Consider using [Apache Commons Text](https://commons.apache.org/proper/commons-text/) + `StringEscapeUtils` methods for various context. Please note there is no way to safely + output script code in most circumstances, regardless of encoding. If calling the HTTP + response writer directly, ensure that the `Content-Type` is set to `text/plain` so it will + not be accidentally interpreted by HTML by modern browsers. + ``` + // Get user input + String htmlInput = request.getParameter("userInput"); + // Encode the input using the Html4 encoder + String htmlEncoded = StringEscapeUtils.escapeHtml4(htmlInput); + // Force the HTTP response to be content type of text/plain so it is not interpreted as HTML + response.setContentType("text/plain"); + // Ensure UTF-8 + response.setCharacterEncoding("UTF-8"); + // Write response + response.getWriter().write(htmlEncoded); + ``` + + For more information on XSS see OWASP: + - https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html + severity: "WARNING" + metadata: + shortDescription: "Improper neutralization of input during web page generation + ('Cross-site Scripting')" + category: "security" + cwe: "CWE-79" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + technology: + - "java" + security-severity: "Medium" +- id: java_xxe_rule-XMLRdr + languages: + - "java" + message: | + External XML entities are a feature of XML parsers that allow documents to contain references + to + other documents or data. This feature can be abused to read files, communicate with external + hosts, + exfiltrate data, or cause a Denial of Service (DoS). + + The XMLReaderFactory has been deprecated. It is recommended that + [SAXParserFactory](https://docs.oracle.com/javase/9/docs/api/javax/xml/parsers/SAXParserFactory.html) + be used + instead. Additionally when using the SAXParser it must be configured to disallow doctypes, + which will + protect against the majority of XXE attacks. + + Example creating a SAXParser with disallowing the doctypes feature enabled: + ``` + // Create a SAXParserFactory + SAXParserFactory saxParserFactory = SAXParserFactory.newInstance(); + // Enable the feature which disallows + - pattern: | + {dangerouslySetInnerHTML: ...} + severity: "WARNING" + message: | + The application was found calling `dangerouslySetInnerHTML` which may lead to Cross Site + Scripting (XSS). By default, React components will encode the data properly before rendering. + Calling `dangerouslySetInnerHTML` disables this encoding and allows raw markup + and JavaScript to be executed. + + XSS is an attack which exploits a web application or system to treat + user input as markup or script code. It is important to encode the data, depending on the + specific context it is used in. There are at least six context types: + + - Inside HTML tags `
context 1
` + - Inside attributes: `
` + - Inside event attributes `` + - Inside script blocks: `` + - Unsafe element HTML assignment: `element.innerHTML = "context 5"` + - Inside URLs: `link` + + Script blocks alone have multiple ways they need to be encoded. Extra care must be taken if + user input + is ever output inside of script tags. + + User input that is displayed within the application must be encoded, sanitized or validated + to ensure it cannot be treated as HTML or executed as Javascript code. Care must also be + taken + to not mix server-side templating with client-side templating, as the server-side templating + will + not encode things like {{ 7*7 }} which may execute client-side templating features. + + It is _NOT_ advised to encode user input prior to inserting into a data store. The data will + need to be + encoded depending on context of where it is output. It is much safer to force the displaying + system to + handle the encoding and not attempt to guess how it should be encoded. + + Remove the call to `dangerouslySetInnerHTML` or ensure that the data used in this call does + not come from user-supplied input. + + For more information on dangerously setting inner HTML see: + - https://react.dev/reference/react-dom/components/common#dangerously-setting-the-inner-html + metadata: + cwe: "CWE-79" + owasp: + - "A7:2017-Cross-Site Scripting (XSS)" + - "A03:2021-Injection" + shortDescription: "Improper neutralization of input during web page generation + ('Cross-site Scripting')" + category: "security" + security-severity: "Medium" +- id: javascript_require_rule-non-literal-require + languages: + - "javascript" + - "typescript" + patterns: + - pattern: "require($OBJ)" + - pattern-not: "require('...')" + severity: "WARNING" + message: | + The application was found to dynamically import a module by calling `require` using a + non-literal string. An adversary might be able to read the first line of + arbitrary files. If they had write access to the file system, they may also be able to + execute arbitrary code. + + To remediate this issue, use a hardcoded string literal when calling `require`. Never call it + it with dynamically created variables or user-supplied data. + metadata: + cwe: "CWE-95" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + shortDescription: "Improper neutralization of directives in dynamically evaluated + code ('Eval Injection')" + category: "security" + # yamllint disable + source-rule-url: "https://github.com/nodesecurity/eslint-plugin-security/blob/master/rules/detect-non-literal-require.js" + # yamllint enable + security-severity: "Low" +- id: javascript_timing_rule-possible-timing-attacks + languages: + - "javascript" + patterns: + - pattern-not: "if ($Z == null) { ... };" + - pattern-not: "if ($Z === null) { ... };" + - pattern-not: "if ($Z != null) { ... };" + - pattern-not: "if ($Z !== null) { ... };" + - pattern-not: "if ($Q != undefined) { ... };" + - pattern-not: "if ($Q !== undefined) { ... };" + - pattern-not: "if ($Q == undefined) { ... };" + - pattern-not: "if ($Q === undefined) { ... };" + - pattern-not: "return $Y == null;" + - pattern-not: "return $Y === null;" + - pattern-not: "return $Y != null;" + - pattern-not: "return $Y !== null;" + - pattern-not: "return $Y == undefined;" + - pattern-not: "return $Y === undefined;" + - pattern-not: "return $Y != undefined;" + - pattern-not: "return $Y !== undefined;" + - pattern-either: + - pattern: | + if (password == $X) { + ... + } + - pattern: | + if ($X == password) { + ... + } + - pattern: | + if (password === $X) { + ... + } + - pattern: | + if ($X === password) { + ... + } + - pattern: | + if (pass == $X) { + ... + } + - pattern: | + if ($X == pass) { + ... + } + - pattern: | + if (pass === $X) { + ... + } + - pattern: | + if ($X === pass) { + ... + } + - pattern: | + if (secret == $X) { + ... + } + - pattern: | + if ($X == secret) { + ... + } + - pattern: | + if (secret === $X) { + ... + } + - pattern: | + if ($X === secret) { + ... + } + - pattern: | + if (api == $X) { + ... + } + - pattern: | + if ($X == api) { + ... + } + - pattern: | + if (api === $X) { + ... + } + - pattern: | + if ($X === api) { + ... + } + - pattern: | + if (apiKey == $X) { + ... + } + - pattern: | + if ($X == apiKey) { + ... + } + - pattern: | + if (apiKey === $X) { + ... + } + - pattern: | + if ($X === apiKey) { + ... + } + - pattern: | + if (apiSecret == $X) { + ... + } + - pattern: | + if ($X == apiSecret) { + ... + } + - pattern: | + if (apiSecret === $X) { + ... + } + - pattern: | + if ($X === apiSecret) { + ... + } + - pattern: | + if (token == $X) { + ... + } + - pattern: | + if ($X == token) { + ... + } + - pattern: | + if (token === $X) { + ... + } + - pattern: | + if ($X === token) { + ... + } + - pattern: | + if (hash == $X) { + ... + } + - pattern: | + if ($X == hash) { + ... + } + - pattern: | + if (hash === $X) { + ... + } + - pattern: | + if ($X === hash) { + ... + } + - pattern: | + if (auth_token == $X) { + ... + } + - pattern: | + if ($X == auth_token) { + ... + } + - pattern: | + if (auth_token === $X) { + ... + } + - pattern: | + if ($X === auth_token) { + ... + } + - pattern: | + if (password != $X) { + ... + } + - pattern: | + if ($X != password) { + ... + } + - pattern: | + if (password !== $X) { + ... + } + - pattern: | + if ($X !== password) { + ... + } + - pattern: | + if (pass != $X) { + ... + } + - pattern: | + if ($X != pass) { + ... + } + - pattern: | + if (pass !== $X) { + ... + } + - pattern: | + if ($X !== pass) { + ... + } + - pattern: | + if (secret != $X) { + ... + } + - pattern: | + if ($X != secret) { + ... + } + - pattern: | + if (secret !== $X) { + ... + } + - pattern: | + if ($X !== secret) { + ... + } + - pattern: | + if (api != $X) { + ... + } + - pattern: | + if ($X != api) { + ... + } + - pattern: | + if (api !== $X) { + ... + } + - pattern: | + if ($X !== api) { + ... + } + - pattern: | + if (apiKey != $X) { + ... + } + - pattern: | + if ($X != apiKey) { + ... + } + - pattern: | + if (apiKey !== $X) { + ... + } + - pattern: | + if ($X !== apiKey) { + ... + } + - pattern: | + if (apiSecret != $X) { + ... + } + - pattern: | + if ($X != apiSecret) { + ... + } + - pattern: | + if (apiSecret !== $X) { + ... + } + - pattern: | + if ($X !== apiSecret) { + ... + } + - pattern: | + if (token != $X) { + ... + } + - pattern: | + if ($X != token) { + ... + } + - pattern: | + if (token !== $X) { + ... + } + - pattern: | + if ($X !== token) { + ... + } + - pattern: | + if (hash != $X) { + ... + } + - pattern: | + if ($X != hash) { + ... + } + - pattern: | + if (hash !== $X) { + ... + } + - pattern: | + if ($X !== hash) { + ... + } + - pattern: | + if (auth_token != $X) { + ... + } + - pattern: | + if ($X != auth_token) { + ... + } + - pattern: | + if (auth_token !== $X) { + ... + } + - pattern: | + if ($X !== auth_token) { + ... + } + - pattern: | + return $X === auth_token; + - pattern: | + return auth_token === $X; + - pattern: | + return $X === token; + - pattern: | + return token === $X; + - pattern: | + return $X === hash; + - pattern: | + return hash === $X; + - pattern: | + return $X === password; + - pattern: | + return password === $X; + - pattern: | + return $X === pass; + - pattern: | + return pass === $X; + - pattern: | + return $X === apiKey; + - pattern: | + return apiKey === $X; + - pattern: | + return $X === apiSecret; + - pattern: | + return apiSecret === $X; + - pattern: | + return $X === api_key; + - pattern: | + return api_key === $X; + - pattern: | + return $X === api_secret; + - pattern: | + return api_secret === $X; + - pattern: | + return $X === secret; + - pattern: | + return secret === $X; + - pattern: | + return $X === api; + - pattern: | + return api === $X; + - pattern: | + return $X == auth_token; + - pattern: | + return auth_token == $X; + - pattern: | + return $X == token; + - pattern: | + return token == $X; + - pattern: | + return $X == hash; + - pattern: | + return hash == $X; + - pattern: | + return $X == password; + - pattern: | + return password == $X; + - pattern: | + return $X == pass; + - pattern: | + return pass == $X; + - pattern: | + return $X == apiKey; + - pattern: | + return apiKey == $X; + - pattern: | + return $X == apiSecret; + - pattern: | + return apiSecret == $X; + - pattern: | + return $X == api_key; + - pattern: | + return api_key == $X; + - pattern: | + return $X == api_secret; + - pattern: | + return api_secret == $X; + - pattern: | + return $X == secret; + - pattern: | + return secret == $X; + - pattern: | + return $X == api; + - pattern: | + return api == $X; + - pattern: | + return $X !== auth_token; + - pattern: | + return auth_token !== $X; + - pattern: | + return $X !== token; + - pattern: | + return token !== $X; + - pattern: | + return $X !== hash; + - pattern: | + return hash !== $X; + - pattern: | + return $X !== password; + - pattern: | + return password !== $X; + - pattern: | + return $X !== pass; + - pattern: | + return pass !== $X; + - pattern: | + return $X !== apiKey; + - pattern: | + return apiKey !== $X; + - pattern: | + return $X !== apiSecret; + - pattern: | + return apiSecret !== $X; + - pattern: | + return $X !== api_key; + - pattern: | + return api_key !== $X; + - pattern: | + return $X !== api_secret; + - pattern: | + return api_secret !== $X; + - pattern: | + return $X !== secret; + - pattern: | + return secret !== $X; + - pattern: | + return $X !== api; + - pattern: | + return api !== $X; + - pattern: | + return $X != auth_token; + - pattern: | + return auth_token != $X; + - pattern: | + return $X != token; + - pattern: | + return token != $X; + - pattern: | + return $X != hash; + - pattern: | + return hash != $X; + - pattern: | + return $X != password; + - pattern: | + return password != $X; + - pattern: | + return $X != pass; + - pattern: | + return pass != $X; + - pattern: | + return $X != apiKey; + - pattern: | + return apiKey != $X; + - pattern: | + return $X != apiSecret; + - pattern: | + return apiSecret != $X; + - pattern: | + return $X != api_key; + - pattern: | + return api_key != $X; + - pattern: | + return $X != api_secret; + - pattern: | + return api_secret != $X; + - pattern: | + return $X != secret; + - pattern: | + return secret != $X; + - pattern: | + return $X != api; + - pattern: | + return api != $X; + severity: "WARNING" + message: | + The application was found executing string comparisons using one of `===`, `!==`, `==` or `!=` + against security sensitive values. String comparisons like this are not constant time, meaning + the + first character found not to match in the two strings will immediately exit the conditional + statement. + This allows an adversary to calculate or observe small timing differences depending on the + strings + passed to this comparison. This potentially allows an adversary the ability to brute force a + string + that will match the expected value by monitoring different character values. + + To remediate this issue, use the `crypto.timingSafeEqual` method when comparing strings. + + Example using `crypto.timingSafeEqual` to safely compare strings: + ``` + function constantTimeIsPasswordEqual(userInput) { + // Retrieve the password from a secure data store such as a KMS or Hashicorp's vault. + const password = getPasswordFromSecureDataStore(); + // Use crypto timingSafeEqual to ensure the comparison is done in constant time. + return crypto.timingSafeEqual(Buffer.from(userInput, 'utf-8'), Buffer.from(password, + 'utf-8')); + } + ``` + + For more information on constant time comparison see: + - https://nodejs.org/api/crypto.html#crypto_crypto_timingsafeequal_a_b + metadata: + cwe: "CWE-208" + shortDescription: "Observable timing discrepancy" + category: "security" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + security-severity: "Medium" +- id: javascript_xss_rule-mustache-escape + languages: + - "javascript" + - "typescript" + patterns: + - pattern-inside: | + $OBJ = require('mustache') + ... + - pattern-either: + - pattern: | + $OBJ.escape = function($TEXT) { + ... + return $TEXT; + } + - patterns: + - metavariable-regex: + metavariable: "$X" + regex: "\"\\{\\{\\{(.+?)\\}\\}\\}\"" + - pattern: "$OBJ.render($X, ... )" + - patterns: + - metavariable-regex: + metavariable: "$Y" + regex: "\"\\{\\{\\&(.+?)\\}\\}\"" + - pattern: "$OBJ.render($Y, ... )" + severity: "WARNING" + message: | + Markup escaping disabled. This can be used with some template engines to escape + disabling of HTML entities, which can lead to XSS attacks. + metadata: + cwe: "CWE-79" + owasp: + - "A7:2017-Cross-Site Scripting (XSS)" + - "A03:2021-Injection" + category: "security" + shortDescription: "Improper neutralization of input during web page generation + (XSS)" + # yamllint enable + security-severity: "Medium" +- id: python_assert_rule-assert-used + languages: + - "python" + message: | + The application was found using `assert` in non-test code. Usually reserved for debug and test + code, the `assert` + function is commonly used to test conditions before continuing execution. However, enclosed + code will be removed + when compiling Python code to optimized byte code. Depending on the assertion and subsequent + logic, this could + lead to undefined behavior of the application or application crashes. + + To remediate this issue, remove the `assert` calls. If necessary, replace them with either `if` + conditions or + `try/except` blocks. + + Example using `try/except` instead of `assert`: + ``` + # Below try/except is equal to the assert statement of: + # assert user.is_authenticated(), "user must be authenticated" + try: + if not user.is_authenticated(): + raise AuthError("user must be authenticated") + except AuthError as e: + # Handle error + # ... + # Return, do not continue processing + return + ``` + metadata: + cwe: "CWE-754" + category: "security" + shortDescription: "Improper check for unusual or exceptional conditions" + owasp: + - "A6:2017-Security Misconfiguration" + - "A05:2021-Security Misconfiguration" + security-severity: "Info" + patterns: + - pattern: "assert(...)" + - pattern-not-inside: | + import pytest + ... + - pattern-not-inside: | + import unittest + ... + severity: "INFO" +- id: python_bind-all-interfaces_rule-general-bindall-interfaces + languages: + - "python" + message: | + Binding to all network interfaces can potentially open up a service to + traffic on unintended interfaces, that may not be properly documented or + secured. By passing "0.0.0.0", "::" or an empty string as the address to the `socket.bind` + function, + the application will bind to all interfaces. + + Consider passing in the interface ip address through an environment variable, + configuration file, or by determining the primary interface(s) IP address. + + Example getting the IP address from an environment variable `IP_ADDRESS`: + ``` + # Get the IP_ADDRESS env variable, or bind to + # 127.0.0.1 if it is not set + address = os.getenv("IP_ADDRESS", "127.0.0.1") + # Create an internet socket + sock = socket.socket(socket.AF_INET) + # Set the port to listen on + port = 9777 + # Bind to the address and port combination + sock.bind((address, port)) + # Listen for connections + sock.listen() + # Handle the connection + ``` + patterns: + - pattern-either: + - pattern: | + $S = socket.socket(...) + ... + $S.bind(("0.0.0.0", ...)) + - pattern: | + $S = socket.socket(...) + ... + $S.bind(("::", ...)) + - pattern: | + $S = socket.socket(...) + ... + $S.bind(("", ...)) + metadata: + category: "security" + owasp: + - "A6:2017-Security Misconfiguration" + - "A05:2021-Security Misconfiguration" + shortDescription: "Binding to an unrestricted IP address" + cwe: "CWE-1327" + security-severity: "Low" + severity: "INFO" +- id: python_crypto_rule-cipher-modes + languages: + - "python" + message: | + Cryptographic algorithms provide many different modes of operation, only some of which provide + message integrity. Without message integrity it could be possible for an adversary to attempt + to tamper with the ciphertext which could lead to compromising the encryption key. Newer + algorithms + apply message integrity to validate ciphertext has not been tampered with. + + Instead of using an algorithm that requires configuring a cipher mode, an algorithm + that has built-in message integrity should be used. Consider using `ChaCha20Poly1305` or + `AES-256-GCM` instead. + + For older applications that don't have support for `ChaCha20Poly1305`, `AES-256-GCM` is + recommended, however it has many drawbacks: + - Slower than `ChaCha20Poly1305`. + - Catastrophic failure if nonce values are reused. + + Example using `ChaCha20Poly1305`: + ``` + import os + # Import ChaCha20Poly1305 from cryptography + from cryptography.hazmat.primitives.ciphers.aead import ChaCha20Poly1305 + # Our plaintext to encrypt + plain_text = b"Secret text to encrypt" + # We do not require authenticated but unencrypted data, so set to None + aad = None + # Generate a secure key + key = ChaCha20Poly1305.generate_key() + # Create a new ChaCha20Poly1305 instance with our secure key + chacha = ChaCha20Poly1305(key) + # Note: nonce values _must_ be regenerated every time they are used. + nonce = os.urandom(12) + # Encrypt our plaintext + cipher_text = chacha.encrypt(nonce, plain_text, aad) + # Decrypt the plain text using the nonce and cipher_text + chacha.decrypt(nonce, cipher_text, aad) + ``` + + Example using `AESGCM`: + ``` + import os + # Import AESGCM from cryptography + from cryptography.hazmat.primitives.ciphers.aead import AESGCM + # Our plaintext to encrypt + plain_text = b"Secret text to encrypt" + # We do not require authenticated but unencrypted data, so set to None + aad = None + # Generate a secure key + key = AESGCM.generate_key(bit_length=128) + # Create a new AESGCM instance with our secure key + aesgcm = AESGCM(key) + # Note: nonce values _must_ be regenerated every time they are used. + nonce = os.urandom(12) + # Encrypt our plaintext + cipher_text = aesgcm.encrypt(nonce, plain_text, aad) + # Decrypt the plain text using the nonce and cipher_text + aesgcm.decrypt(nonce, cipher_text, aad) + ``` + + For more information on the cryptography module see: + - https://cryptography.io/en/latest/ + metadata: + cwe: "CWE-327" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + category: "security" + shortDescription: "Use of a broken or risky cryptographic algorithm" + security-severity: "Medium" + pattern: "cryptography.hazmat.primitives.ciphers.modes.ECB(...)" + severity: "WARNING" +- id: python_crypto_rule-crypto-cipher-blowfish + languages: + - "python" + message: | + The Blowfish encryption algorithm was meant as a drop-in replacement for DES and was created in + 1993. Smaller key sizes may make the ciphertext vulnerable to [birthday + attacks](https://en.wikipedia.org/wiki/Birthday_attack). While no known attacks against + Blowfish + exist, it should never be used to encrypt files over 4GB in size. If possible consider + using ChaCha20Poly1305 or AES-GCM instead of Blowfish. + + For older applications that don't have support for `ChaCha20Poly1305`, `AES-256-GCM` is + recommended, however it has many drawbacks: + - Slower than `ChaCha20Poly1305`. + - Catastrophic failure if nonce values are reused. + + Note that the `Crypto` and `Cryptodome` Python packages are no longer recommended for + new applications, instead consider using the [cryptography](https://cryptography.io/) package. + + Example using `ChaCha20Poly1305`: + ``` + import os + # Import ChaCha20Poly1305 from cryptography + from cryptography.hazmat.primitives.ciphers.aead import ChaCha20Poly1305 + # Our plaintext to encrypt + plain_text = b"Secret text to encrypt" + # We do not require authenticated but unencrypted data, so set to None + aad = None + # Generate a secure key + key = ChaCha20Poly1305.generate_key() + # Create a new ChaCha20Poly1305 instance with our secure key + chacha = ChaCha20Poly1305(key) + # Note: nonce values _must_ be regenerated every time they are used. + nonce = os.urandom(12) + # Encrypt our plaintext + cipher_text = chacha.encrypt(nonce, plain_text, aad) + # Decrypt the plain text using the nonce and cipher_text + chacha.decrypt(nonce, cipher_text, aad) + ``` + + Example using `AESGCM`: + ``` + import os + # Import AESGCM from cryptography + from cryptography.hazmat.primitives.ciphers.aead import AESGCM + # Our plaintext to encrypt + plain_text = b"Secret text to encrypt" + # We do not require authenticated but unencrypted data, so set to None + aad = None + # Generate a secure key + key = AESGCM.generate_key(bit_length=128) + # Create a new AESGCM instance with our secure key + aesgcm = AESGCM(key) + # Note: nonce values _must_ be regenerated every time they are used. + nonce = os.urandom(12) + # Encrypt our plaintext + cipher_text = aesgcm.encrypt(nonce, plain_text, aad) + # Decrypt the plain text using the nonce and cipher_text + aesgcm.decrypt(nonce, cipher_text, aad) + ``` + + For more information on the cryptography module see: + - https://cryptography.io/en/latest/ + metadata: + cwe: "CWE-327" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + category: "security" + shortDescription: "Use of a broken or risky cryptographic algorithm" + security-severity: "Medium" + patterns: + - pattern-either: + - pattern: "Cryptodome.Cipher.Blowfish.new(...)" + - pattern: "Crypto.Cipher.Blowfish.new(...)" + severity: "WARNING" +- id: python_crypto_rule-crypto-cipher-des + languages: + - "python" + message: | + DES, TripleDES, RC2 and RC4 are all considered broken or insecure cryptographic algorithms. + Newer algorithms apply message integrity to validate ciphertext has not been tampered + with. Consider using `ChaCha20Poly1305` instead as it is easier and faster than the + alternatives such as `AES-256-GCM`. + + For older applications that don't have support for `ChaCha20Poly1305`, + `AES-256-GCM` is recommended, however it has many drawbacks: + - Slower than `ChaCha20Poly1305`. + - Catastrophic failure if nonce values are reused. + + Note that the `Crypto` and `Cryptodome` Python packages are no longer recommended for + new applications, instead consider using the [cryptography](https://cryptography.io/) package. + + Example using `ChaCha20Poly1305`: + ``` + import os + # Import ChaCha20Poly1305 from cryptography + from cryptography.hazmat.primitives.ciphers.aead import ChaCha20Poly1305 + # Our plaintext to encrypt + plain_text = b"Secret text to encrypt" + # We do not require authenticated but unencrypted data, so set to None + aad = None + # Generate a secure key + key = ChaCha20Poly1305.generate_key() + # Create a new ChaCha20Poly1305 instance with our secure key + chacha = ChaCha20Poly1305(key) + # Note: nonce values _must_ be regenerated every time they are used. + nonce = os.urandom(12) + # Encrypt our plaintext + cipher_text = chacha.encrypt(nonce, plain_text, aad) + # Decrypt the plain text using the nonce and cipher_text + chacha.decrypt(nonce, cipher_text, aad) + ``` + + Example using `AESGCM`: + ``` + import os + # Import AESGCM from cryptography + from cryptography.hazmat.primitives.ciphers.aead import AESGCM + # Our plaintext to encrypt + plain_text = b"Secret text to encrypt" + # We do not require authenticated but unencrypted data, so set to None + aad = None + # Generate a secure key + key = AESGCM.generate_key(bit_length=128) + # Create a new AESGCM instance with our secure key + aesgcm = AESGCM(key) + # Note: nonce values _must_ be regenerated every time they are used. + nonce = os.urandom(12) + # Encrypt our plaintext + cipher_text = aesgcm.encrypt(nonce, plain_text, aad) + # Decrypt the plain text using the nonce and cipher_text + aesgcm.decrypt(nonce, cipher_text, aad) + ``` + + For more information on the cryptography module see: + - https://cryptography.io/en/latest/ + metadata: + cwe: "CWE-327" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + category: "security" + shortDescription: "Use of a broken or risky cryptographic algorithm" + security-severity: "Medium" + patterns: + - pattern-either: + - pattern: "Cryptodome.Cipher.DES.new(...)" + - pattern: "Crypto.Cipher.DES.new(...)" + severity: "WARNING" +- id: python_crypto_rule-crypto-cipher-rc2 + languages: + - "python" + message: | + DES, TripleDES, RC2 and RC4 are all considered broken or insecure cryptographic algorithms. + Newer algorithms apply message integrity to validate ciphertext has not been tampered + with. Consider using `ChaCha20Poly1305` instead as it is easier and faster than the + alternatives such as `AES-256-GCM`. + + For older applications that don't have support for `ChaCha20Poly1305`, + `AES-256-GCM` is recommended, however it has many drawbacks: + - Slower than `ChaCha20Poly1305`. + - Catastrophic failure if nonce values are reused. + + Note that the `Crypto` and `Cryptodome` Python packages are no longer recommended for + new applications, instead consider using the [cryptography](https://cryptography.io/) package. + + Example using `ChaCha20Poly1305`: + ``` + import os + # Import ChaCha20Poly1305 from cryptography + from cryptography.hazmat.primitives.ciphers.aead import ChaCha20Poly1305 + # Our plaintext to encrypt + plain_text = b"Secret text to encrypt" + # We do not require authenticated but unencrypted data, so set to None + aad = None + # Generate a secure key + key = ChaCha20Poly1305.generate_key() + # Create a new ChaCha20Poly1305 instance with our secure key + chacha = ChaCha20Poly1305(key) + # Note: nonce values _must_ be regenerated every time they are used. + nonce = os.urandom(12) + # Encrypt our plaintext + cipher_text = chacha.encrypt(nonce, plain_text, aad) + # Decrypt the plain text using the nonce and cipher_text + chacha.decrypt(nonce, cipher_text, aad) + ``` + + Example using `AESGCM`: + ``` + import os + # Import AESGCM from cryptography + from cryptography.hazmat.primitives.ciphers.aead import AESGCM + # Our plaintext to encrypt + plain_text = b"Secret text to encrypt" + # We do not require authenticated but unencrypted data, so set to None + aad = None + # Generate a secure key + key = AESGCM.generate_key(bit_length=128) + # Create a new AESGCM instance with our secure key + aesgcm = AESGCM(key) + # Note: nonce values _must_ be regenerated every time they are used. + nonce = os.urandom(12) + # Encrypt our plaintext + cipher_text = aesgcm.encrypt(nonce, plain_text, aad) + # Decrypt the plain text using the nonce and cipher_text + aesgcm.decrypt(nonce, cipher_text, aad) + ``` + + For more information on the cryptography module see: + - https://cryptography.io/en/latest/ + metadata: + cwe: "CWE-327" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + category: "security" + shortDescription: "Use of a broken or risky cryptographic algorithm" + security-severity: "Medium" + patterns: + - pattern-either: + - pattern: "Cryptodome.Cipher.ARC2.new(...)" + - pattern: "Crypto.Cipher.ARC2.new" + severity: "WARNING" +- id: python_crypto_rule-crypto-cipher-rc4 + languages: + - "python" + message: | + DES, TripleDES, RC2 and RC4 are all considered broken or insecure cryptographic algorithms. + Newer algorithms apply message integrity to validate ciphertext has not been tampered + with. Consider using `ChaCha20Poly1305` instead as it is easier and faster than the + alternatives such as `AES-256-GCM`. + + For older applications that don't have support for `ChaCha20Poly1305`, + `AES-256-GCM` is recommended, however it has many drawbacks: + - Slower than `ChaCha20Poly1305`. + - Catastrophic failure if nonce values are reused. + + Note that the `Crypto` and `Cryptodome` Python packages are no longer recommended for + new applications, instead consider using the [cryptography](https://cryptography.io/) package. + + Example using `ChaCha20Poly1305`: + ``` + import os + # Import ChaCha20Poly1305 from cryptography + from cryptography.hazmat.primitives.ciphers.aead import ChaCha20Poly1305 + # Our plaintext to encrypt + plain_text = b"Secret text to encrypt" + # We do not require authenticated but unencrypted data, so set to None + aad = None + # Generate a secure key + key = ChaCha20Poly1305.generate_key() + # Create a new ChaCha20Poly1305 instance with our secure key + chacha = ChaCha20Poly1305(key) + # Note: nonce values _must_ be regenerated every time they are used. + nonce = os.urandom(12) + # Encrypt our plaintext + cipher_text = chacha.encrypt(nonce, plain_text, aad) + # Decrypt the plain text using the nonce and cipher_text + chacha.decrypt(nonce, cipher_text, aad) + ``` + + Example using `AESGCM`: + ``` + import os + # Import AESGCM from cryptography + from cryptography.hazmat.primitives.ciphers.aead import AESGCM + # Our plaintext to encrypt + plain_text = b"Secret text to encrypt" + # We do not require authenticated but unencrypted data, so set to None + aad = None + # Generate a secure key + key = AESGCM.generate_key(bit_length=128) + # Create a new AESGCM instance with our secure key + aesgcm = AESGCM(key) + # Note: nonce values _must_ be regenerated every time they are used. + nonce = os.urandom(12) + # Encrypt our plaintext + cipher_text = aesgcm.encrypt(nonce, plain_text, aad) + # Decrypt the plain text using the nonce and cipher_text + aesgcm.decrypt(nonce, cipher_text, aad) + ``` + + For more information on the cryptography module see: + - https://cryptography.io/en/latest/ + metadata: + cwe: "CWE-327" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + category: "security" + shortDescription: "Use of a broken or risky cryptographic algorithm" + security-severity: "Medium" + patterns: + - pattern-either: + - pattern: "Cryptodome.Cipher.ARC4.new(...)" + - pattern: "Crypto.Cipher.ARC4.new(...)" + severity: "WARNING" +- id: python_crypto_rule-crypto-cipher-xor + languages: + - "python" + message: | + The application was found using the `xor` algorithm, which can be trivially decoded. + Newer algorithms apply message integrity to validate ciphertext has not been tampered + with. Consider using `ChaCha20Poly1305` instead as it is easier and faster than the + alternatives such as `AES-256-GCM`. + + For older applications that don't have support for `ChaCha20Poly1305`, + `AES-256-GCM` is recommended, however it has many drawbacks: + - Slower than `ChaCha20Poly1305`. + - Catastrophic failure if nonce values are reused. + + Note that the `Crypto` and `Cryptodome` Python packages are no longer recommended for + new applications, instead consider using the [cryptography](https://cryptography.io/) package. + + Example using `ChaCha20Poly1305`: + ``` + import os + # Import ChaCha20Poly1305 from cryptography + from cryptography.hazmat.primitives.ciphers.aead import ChaCha20Poly1305 + # Our plaintext to encrypt + plain_text = b"Secret text to encrypt" + # We do not require authenticated but unencrypted data, so set to None + aad = None + # Generate a secure key + key = ChaCha20Poly1305.generate_key() + # Create a new ChaCha20Poly1305 instance with our secure key + chacha = ChaCha20Poly1305(key) + # Note: nonce values _must_ be regenerated every time they are used. + nonce = os.urandom(12) + # Encrypt our plaintext + cipher_text = chacha.encrypt(nonce, plain_text, aad) + # Decrypt the plain text using the nonce and cipher_text + chacha.decrypt(nonce, cipher_text, aad) + ``` + + Example using `AESGCM`: + ``` + import os + # Import AESGCM from cryptography + from cryptography.hazmat.primitives.ciphers.aead import AESGCM + # Our plaintext to encrypt + plain_text = b"Secret text to encrypt" + # We do not require authenticated but unencrypted data, so set to None + aad = None + # Generate a secure key + key = AESGCM.generate_key(bit_length=128) + # Create a new AESGCM instance with our secure key + aesgcm = AESGCM(key) + # Note: nonce values _must_ be regenerated every time they are used. + nonce = os.urandom(12) + # Encrypt our plaintext + cipher_text = aesgcm.encrypt(nonce, plain_text, aad) + # Decrypt the plain text using the nonce and cipher_text + aesgcm.decrypt(nonce, cipher_text, aad) + ``` + + For more information on the cryptography module see: + - https://cryptography.io/en/latest/ + metadata: + cwe: "CWE-327" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + category: "security" + shortDescription: "Use of a broken or risky cryptographic algorithm" + security-severity: "Medium" + patterns: + - pattern-either: + - pattern: "Cryptodome.Cipher.XOR.new(...)" + - pattern: "Crypto.Cipher.XOR.new(...)" + severity: "WARNING" +- id: python_crypto_rule-crypto-encrypt-dsa-rsa + languages: + - "python" + message: | + The application is generating an RSA key that is less than the recommended 2048 bits. + The National Institute of Standards and Technology (NIST) deprecated signing Digital + Certificates that contained RSA Public Keys of 1024 bits in December 2010. While + 1024-bit RSA keys have not been factored yet, advances in compute may make it possible + in the near future. + + Consider upgrading to the newer asymmetric algorithm such as `X25519` which handles + the complexities of generating key pairs and choosing correct key sizes for you: + ``` + from cryptography.hazmat.primitives.asymmetric.x25519 import X25519PrivateKey + + # Generate a private key for use in the exchange. + private_key = X25519PrivateKey.generate() + # Work with private key/exchange with a peer's + # public key to created a shared and derived key + # ... + ``` + + Otherwise use a key size greater than 2048 when generating RSA keys: + ``` + from cryptography.hazmat.primitives.asymmetric import rsa + # Generate a private key of 4096 bits + private_key = rsa.generate_private_key( + # do not change the exponent value from 65537 + public_exponent=65537, + key_size=4096, + ) + # Work with the private key to sign/encrypt data + # ... + ``` + + For more information on using the cryptography module see: + - https://cryptography.io/en/latest + metadata: + cwe: "CWE-326" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + category: "security" + shortDescription: "Inadequate encryption strength" + security-severity: "Medium" + patterns: + - pattern-either: + - pattern: | + cryptography.hazmat.primitives.asymmetric.rsa.generate_private_key(...,key_size=$SIZE,...) + - pattern: | + cryptography.hazmat.primitives.asymmetric.rsa.generate_private_key($EXP, $SIZE,...) + - pattern: | + cryptography.hazmat.primitives.asymmetric.rsa.generate_private_key($SIZE, ...) + - pattern: | + cryptography.hazmat.primitives.asymmetric.dsa.generate_private_key(...,key_size=$SIZE,...) + - pattern: | + cryptography.hazmat.primitives.asymmetric.dsa.generate_private_key($EXP, $SIZE, ...) + - pattern: "cryptography.hazmat.primitives.asymmetric.dsa.generate_private_key($SIZE,...)" + - pattern: "Crypto.PublicKey.RSA.generate($SIZE, ...)" + - pattern: "Crypto.PublicKey.DSA.generate($SIZE, ...)" + - pattern: "Cryptodome.PublicKey.DSA.generate($SIZE, ...)" + - pattern: "Cryptodome.PublicKey.RSA.generate($SIZE, ...)" + - pattern: "Crypto.PublicKey.DSA.generate(bits=$SIZE, ...)" + - pattern: "Cryptodome.PublicKey.DSA.generate(bits=$SIZE, ...)" + - pattern: "pycrypto_rsa.generate(bits=$SIZE, ...)" + - pattern: "pycrypto_dsa.generate(bits=$SIZE, ...)" + - pattern: "pycryptodomex_rsa.generate(bits=$SIZE, ...)" + - pattern: "pycryptodomex_rsa.generate($SIZE, ...)" + - pattern: "pycryptodomex_dsa.generate(bits=$SIZE, ...)" + - pattern: "pycryptodomex_dsa.generate($SIZE, ...)" + - metavariable-comparison: + comparison: "$SIZE < 2048" + metavariable: "$SIZE" + severity: "ERROR" +- id: python_crypto_rule-crypto-encrypt-ec + languages: + - "python" + message: | + The application was found using an insufficient curve size for the Elliptical + Cryptography (EC) asymmetric algorithm. NIST recommends using a key size of + 224 or greater. + + To remediate this issue, replace the current key size with `ec.SECP384R1`, + + Example using `ec.SECP384R1`: + ``` + from cryptography.hazmat.primitives.asymmetric import ec + # Generate an EC private key using SECP384R1 + private_key = ec.generate_private_key( + ec.SECP384R1() + ) + # Work with/sign data using the key + # ... + ``` + + For more information on the cryptography module's EC section see: + - https://cryptography.io/en/latest/hazmat/primitives/asymmetric/ec/ + metadata: + cwe: "CWE-326" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + category: "security" + shortDescription: "Inadequate encryption strength" + security-severity: "Medium" + patterns: + - pattern-inside: |- + cryptography.hazmat.primitives.asymmetric.ec.generate_private_key(...) + - pattern: "cryptography.hazmat.primitives.asymmetric.ec.$SIZE" + - metavariable-pattern: + metavariable: "$SIZE" + pattern-either: + - pattern: "SECP192R1" + - pattern: "SECT163K1" + - pattern: "SECT163R2" + - focus-metavariable: "$SIZE" + severity: "ERROR" +- id: python_crypto_rule-crypto-hash-md5 + languages: + - "python" + message: | + The application was found using an insecure or risky digest or signature algorithm. MD5 + and SHA1 hash algorithms have been found to be vulnerable to producing collisions. + + This means + that two different values, when hashed, can lead to the same hash value. If the application is + trying + to use these hash methods for storing passwords, then it is recommended to switch to a + password hashing + algorithm such as Argon2id or PBKDF2. + It is strongly recommended that a standard digest algorithm be chosen instead as implementing + a custom algorithm is prone to errors. + + Note that the `Crypto` and `Cryptodome` Python packages are no longer recommended for + new applications, instead consider using the [cryptography](https://cryptography.io/) package. + + Example of creating a SHA-384 hash using the `cryptography` package: + ``` + from cryptography.hazmat.primitives import hashes + # Create a SHA384 digest + digest = hashes.Hash(hashes.SHA384()) + # Update the digest with some initial data + digest.update(b"some data to hash") + # Add more data to the digest + digest.update(b"some more data") + # Finalize the digest as bytes + result = digest.finalize() + ``` + + For more information on secure password storage see OWASP: + - https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html + + For more information on the cryptography module see: + - https://cryptography.io/en/latest/ + metadata: + cwe: "CWE-327" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + category: "security" + shortDescription: "Use of a broken or risky cryptographic algorithm" + security-severity: "Medium" + patterns: + - pattern-either: + - pattern: "Crypto.Hash.MD5.new(...)" + - pattern: "Cryptodome.Hash.MD5.new (...)" + severity: "WARNING" +- id: python_crypto_rule-crypto-hash-sha1 + languages: + - "python" + message: | + The application was found using an insecure or risky digest or signature algorithm. MD5 + and SHA1 hash algorithms have been found to be vulnerable to producing collisions. + + This means + that two different values, when hashed, can lead to the same hash value. If the application is + trying + to use these hash methods for storing passwords, then it is recommended to switch to a + password hashing + algorithm such as Argon2id or PBKDF2. + It is strongly recommended that a standard digest algorithm be chosen instead as implementing + a custom algorithm is prone to errors. + + Note that the `Crypto` and `Cryptodome` Python packages are no longer recommended for + new applications, instead consider using the [cryptography](https://cryptography.io/) package. + + Example of creating a SHA-384 hash using the `cryptography` package: + ``` + from cryptography.hazmat.primitives import hashes + # Create a SHA384 digest + digest = hashes.Hash(hashes.SHA384()) + # Update the digest with some initial data + digest.update(b"some data to hash") + # Add more data to the digest + digest.update(b"some more data") + # Finalize the digest as bytes + result = digest.finalize() + ``` + + For more information on secure password storage see OWASP: + - https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html + + For more information on the cryptography module see: + - https://cryptography.io/en/latest/ + metadata: + cwe: "CWE-327" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + category: "security" + shortDescription: "Use of a broken or risky cryptographic algorithm" + security-severity: "Medium" + patterns: + - pattern-either: + - pattern: "Crypto.Hash.SHA.new(...)" + - pattern: "Cryptodome.Hash.SHA.new (...)" + severity: "WARNING" +- id: python_crypto_rule-crypto-hazmat-cipher-arc4 + languages: + - "python" + message: | + DES, TripleDES, RC2 and RC4 are all considered broken or insecure cryptographic algorithms. + Newer algorithms apply message integrity to validate ciphertext has not been tampered + with. Consider using `ChaCha20Poly1305` instead as it is easier and faster than the + alternatives such as `AES-256-GCM`. + + For older applications that don't have support for `ChaCha20Poly1305`, + `AES-256-GCM` is recommended, however it has many drawbacks: + - Slower than `ChaCha20Poly1305`. + - Catastrophic failure if nonce values are reused. + + Example using `ChaCha20Poly1305`: + ``` + import os + # Import ChaCha20Poly1305 from cryptography + from cryptography.hazmat.primitives.ciphers.aead import ChaCha20Poly1305 + # Our plaintext to encrypt + plain_text = b"Secret text to encrypt" + # We do not require authenticated but unencrypted data, so set to None + aad = None + # Generate a secure key + key = ChaCha20Poly1305.generate_key() + # Create a new ChaCha20Poly1305 instance with our secure key + chacha = ChaCha20Poly1305(key) + # Note: nonce values _must_ be regenerated every time they are used. + nonce = os.urandom(12) + # Encrypt our plaintext + cipher_text = chacha.encrypt(nonce, plain_text, aad) + # Decrypt the plain text using the nonce and cipher_text + chacha.decrypt(nonce, cipher_text, aad) + ``` + + Example using `AESGCM`: + ``` + import os + # Import AESGCM from cryptography + from cryptography.hazmat.primitives.ciphers.aead import AESGCM + # Our plaintext to encrypt + plain_text = b"Secret text to encrypt" + # We do not require authenticated but unencrypted data, so set to None + aad = None + # Generate a secure key + key = AESGCM.generate_key(bit_length=128) + # Create a new AESGCM instance with our secure key + aesgcm = AESGCM(key) + # Note: nonce values _must_ be regenerated every time they are used. + nonce = os.urandom(12) + # Encrypt our plaintext + cipher_text = aesgcm.encrypt(nonce, plain_text, aad) + # Decrypt the plain text using the nonce and cipher_text + aesgcm.decrypt(nonce, cipher_text, aad) + ``` + + For more information on the cryptography module see: + - https://cryptography.io/en/latest/ + metadata: + cwe: "CWE-327" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + category: "security" + shortDescription: "Use of a broken or risky cryptographic algorithm" + security-severity: "Medium" + pattern: "cryptography.hazmat.primitives.ciphers.algorithms.ARC4(...)" + severity: "WARNING" +- id: python_crypto_rule-crypto-hazmat-cipher-blowfish + languages: + - "python" + message: | + The Blowfish encryption algorithm was meant as a drop-in replacement for DES and was created in + 1993. Smaller key sizes may make the ciphertext vulnerable to [birthday + attacks](https://en.wikipedia.org/wiki/Birthday_attack). While no known attacks against + Blowfish + exist, it should never be used to encrypt files over 4GB in size. If possible consider + using ChaCha20Poly1305 or AES-GCM instead of Blowfish. + + For older applications that don't have support for `ChaCha20Poly1305`, `AES-256-GCM` is + recommended, however it has many drawbacks: + - Slower than `ChaCha20Poly1305`. + - Catastrophic failure if nonce values are reused. + + Example using `ChaCha20Poly1305`: + ``` + import os + # Import ChaCha20Poly1305 from cryptography + from cryptography.hazmat.primitives.ciphers.aead import ChaCha20Poly1305 + # Our plaintext to encrypt + plain_text = b"Secret text to encrypt" + # We do not require authenticated but unencrypted data, so set to None + aad = None + # Generate a secure key + key = ChaCha20Poly1305.generate_key() + # Create a new ChaCha20Poly1305 instance with our secure key + chacha = ChaCha20Poly1305(key) + # Note: nonce values _must_ be regenerated every time they are used. + nonce = os.urandom(12) + # Encrypt our plaintext + cipher_text = chacha.encrypt(nonce, plain_text, aad) + # Decrypt the plain text using the nonce and cipher_text + chacha.decrypt(nonce, cipher_text, aad) + ``` + + Example using `AESGCM`: + ``` + import os + # Import AESGCM from cryptography + from cryptography.hazmat.primitives.ciphers.aead import AESGCM + # Our plaintext to encrypt + plain_text = b"Secret text to encrypt" + # We do not require authenticated but unencrypted data, so set to None + aad = None + # Generate a secure key + key = AESGCM.generate_key(bit_length=128) + # Create a new AESGCM instance with our secure key + aesgcm = AESGCM(key) + # Note: nonce values _must_ be regenerated every time they are used. + nonce = os.urandom(12) + # Encrypt our plaintext + cipher_text = aesgcm.encrypt(nonce, plain_text, aad) + # Decrypt the plain text using the nonce and cipher_text + aesgcm.decrypt(nonce, cipher_text, aad) + ``` + + For more information on the cryptography module see: + - https://cryptography.io/en/latest/ + metadata: + cwe: "CWE-327" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + category: "security" + shortDescription: "Use of a broken or risky cryptographic algorithm" + security-severity: "Medium" + pattern: "cryptography.hazmat.primitives.ciphers.algorithms.Blowfish(...)" + severity: "WARNING" +- id: python_crypto_rule-crypto-hazmat-cipher-idea + languages: + - "python" + message: | + The IDEA encryption algorithm was meant as a drop-in replacement for DES and was created in + 1991. A number of [vulnerabilities and + exploits](https://en.wikipedia.org/wiki/International_Data_Encryption_Algorithm#Security) have + been identified to work against IDEA and + it is no longer recommended. If possible consider + using ChaCha20Poly1305 or AES-GCM instead of Blowfish. + + For older applications that don't have support for `ChaCha20Poly1305`, `AES-256-GCM` is + recommended, however it has many drawbacks: + - Slower than `ChaCha20Poly1305`. + - Catastrophic failure if nonce values are reused. + + Example using `ChaCha20Poly1305`: + ``` + import os + # Import ChaCha20Poly1305 from cryptography + from cryptography.hazmat.primitives.ciphers.aead import ChaCha20Poly1305 + # Our plaintext to encrypt + plain_text = b"Secret text to encrypt" + # We do not require authenticated but unencrypted data, so set to None + aad = None + # Generate a secure key + key = ChaCha20Poly1305.generate_key() + # Create a new ChaCha20Poly1305 instance with our secure key + chacha = ChaCha20Poly1305(key) + # Note: nonce values _must_ be regenerated every time they are used. + nonce = os.urandom(12) + # Encrypt our plaintext + cipher_text = chacha.encrypt(nonce, plain_text, aad) + # Decrypt the plain text using the nonce and cipher_text + chacha.decrypt(nonce, cipher_text, aad) + ``` + + Example using `AESGCM`: + ``` + import os + # Import AESGCM from cryptography + from cryptography.hazmat.primitives.ciphers.aead import AESGCM + # Our plaintext to encrypt + plain_text = b"Secret text to encrypt" + # We do not require authenticated but unencrypted data, so set to None + aad = None + # Generate a secure key + key = AESGCM.generate_key(bit_length=128) + # Create a new AESGCM instance with our secure key + aesgcm = AESGCM(key) + # Note: nonce values _must_ be regenerated every time they are used. + nonce = os.urandom(12) + # Encrypt our plaintext + cipher_text = aesgcm.encrypt(nonce, plain_text, aad) + # Decrypt the plain text using the nonce and cipher_text + aesgcm.decrypt(nonce, cipher_text, aad) + ``` + + For more information on the cryptography module see: + - https://cryptography.io/en/latest/ + metadata: + cwe: "CWE-327" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + shortDescription: "Use of a Broken or Risky Cryptographic Algorithm" + security-severity: "Medium" + category: "security" + pattern: "cryptography.hazmat.primitives.ciphers.algorithms.IDEA(...)" + severity: "WARNING" +- id: python_crypto_rule-crypto.hazmat-hash-md5 + languages: + - "python" + message: | + The application was found using an insecure or risky digest or signature algorithm. MD2, MD5 + and SHA1 hash algorithms have been found to be vulnerable to producing collisions. + + This means + that two different values, when hashed, can lead to the same hash value. If the application is + trying + to use these hash methods for storing passwords, then it is recommended to switch to a + password hashing + algorithm such as Argon2id or PBKDF2. + It is strongly recommended that a standard digest algorithm be chosen instead as implementing + a custom algorithm is prone to errors. + + Example of creating a SHA-384 hash using the `cryptography` package: + ``` + from cryptography.hazmat.primitives import hashes + # Create a SHA384 digest + digest = hashes.Hash(hashes.SHA384()) + # Update the digest with some initial data + digest.update(b"some data to hash") + # Add more data to the digest + digest.update(b"some more data") + # Finalize the digest as bytes + result = digest.finalize() + ``` + + For more information on secure password storage see OWASP: + - https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html + + For more information on the cryptography module see: + - https://cryptography.io/en/latest/ + metadata: + cwe: "CWE-327" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + shortDescription: "Use of a broken or risky cryptographic algorithm" + security-severity: "Medium" + category: "security" + pattern: "cryptography.hazmat.primitives.hashes.MD5(...)" + severity: "WARNING" +- id: python_crypto_rule-crypto.hazmat-hash-sha1 + languages: + - "python" + message: | + The application was found using an insecure or risky digest or signature algorithm. MD2, MD5 + and SHA1 hash algorithms have been found to be vulnerable to producing collisions. + + This means + that two different values, when hashed, can lead to the same hash value. If the application is + trying + to use these hash methods for storing passwords, then it is recommended to switch to a + password hashing + algorithm such as Argon2id or PBKDF2. + It is strongly recommended that a standard digest algorithm be chosen instead as implementing + a custom algorithm is prone to error. + + Example of creating a SHA-384 hash using the `cryptography` package: + ``` + from cryptography.hazmat.primitives import hashes + # Create a SHA384 digest + digest = hashes.Hash(hashes.SHA384()) + # Update the digest with some initial data + digest.update(b"some data to hash") + # Add more data to the digest + digest.update(b"some more data") + # Finalize the digest as bytes + result = digest.finalize() + ``` + + For more information on secure password storage see OWASP: + - https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html + + For more information on the cryptography module see: + - https://cryptography.io/en/latest/ + metadata: + cwe: "CWE-327" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + category: "security" + shortDescription: "Use of a broken or risky cryptographic algorithm" + security-severity: "Medium" + pattern: "cryptography.hazmat.primitives.hashes.SHA1(...)" + severity: "WARNING" +- id: python_crypto_rule-hash-md2 + languages: + - "python" + message: | + The application was found using an insecure or risky digest or signature algorithm. MD2, MD5 + and SHA1 hash algorithms have been found to be vulnerable to producing collisions. + + This means + that two different values, when hashed, can lead to the same hash value. If the application is + trying + to use these hash methods for storing passwords, then it is recommended to switch to a + password hashing + algorithm such as Argon2id or PBKDF2. + + Note that the `Crypto` and `Cryptodome` Python packages are no longer recommended for + new applications, instead consider using the [cryptography](https://cryptography.io/) package. + + Example of creating a SHA-384 hash using the `cryptography` package: + ``` + from cryptography.hazmat.primitives import hashes + # Create a SHA384 digest + digest = hashes.Hash(hashes.SHA384()) + # Update the digest with some initial data + digest.update(b"some data to hash") + # Add more data to the digest + digest.update(b"some more data") + # Finalize the digest as bytes + result = digest.finalize() + ``` + + For more information on secure password storage see OWASP: + - https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html + + For more information on the cryptography module see: + - https://cryptography.io/en/latest/ + metadata: + cwe: "CWE-327" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + category: "security" + shortDescription: "Use of a broken or risky cryptographic algorithm" + security-severity: "Medium" + patterns: + - pattern-either: + - pattern: "Crypto.Hash.MD2.new(...)" + - pattern: "Cryptodome.Hash.MD2.new (...)" + severity: "WARNING" +- id: python_crypto_rule-hash-md4 + languages: + - "python" + message: | + The application was found using an insecure or risky digest or signature algorithm. MD2, MD4, + MD5 and SHA1 hash algorithms have been found to be vulnerable to producing collisions. + + This means + that two different values, when hashed, can lead to the same hash value. If the application is + trying + to use these hash methods for storing passwords, then it is recommended to switch to a + password hashing + algorithm such as Argon2id or PBKDF2. + + Note that the `Crypto` and `Cryptodome` Python packages are no longer recommended for + new applications, instead consider using the [cryptography](https://cryptography.io/) package. + + Example of creating a SHA-384 hash using the `cryptography` package: + ``` + from cryptography.hazmat.primitives import hashes + # Create a SHA384 digest + digest = hashes.Hash(hashes.SHA384()) + # Update the digest with some initial data + digest.update(b"some data to hash") + # Add more data to the digest + digest.update(b"some more data") + # Finalize the digest as bytes + result = digest.finalize() + ``` + + For more information on secure password storage see OWASP: + - https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html + + For more information on the cryptography module see: + - https://cryptography.io/en/latest/ + metadata: + cwe: "CWE-327" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + category: "security" + shortDescription: "Use of a broken or risky cryptographic algorithm" + security-severity: "Medium" + patterns: + - pattern-either: + - pattern: "Crypto.Hash.MD4.new(...)" + - pattern: "Cryptodome.Hash.MD4.new (...)" + severity: "WARNING" +- id: python_crypto_rule-hash-md5 + languages: + - "python" + message: | + The application was found using an insecure or risky digest or signature algorithm. MD2, MD4, + MD5 and SHA1 hash algorithms have been found to be vulnerable to producing collisions. + + This means + that two different values, when hashed, can lead to the same hash value. If the application is + trying + to use these hash methods for storing passwords, then it is recommended to switch to a + password hashing + algorithm such as Argon2id or PBKDF2. + + Note that the `Crypto` and `Cryptodome` Python packages are no longer recommended for + new applications, instead consider using the [cryptography](https://cryptography.io/) package. + + Example of creating a SHA-384 hash using the `cryptography` package: + ``` + from cryptography.hazmat.primitives import hashes + # Create a SHA384 digest + digest = hashes.Hash(hashes.SHA384()) + # Update the digest with some initial data + digest.update(b"some data to hash") + # Add more data to the digest + digest.update(b"some more data") + # Finalize the digest as bytes + result = digest.finalize() + ``` + + For more information on secure password storage see OWASP: + - https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html + + For more information on the cryptography module see: + - https://cryptography.io/en/latest/ + metadata: + cwe: "CWE-327" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + category: "security" + shortDescription: "Use of a broken or risky cryptographic algorithm" + security-severity: "Medium" + pattern: "hashlib.md5(...)" + severity: "WARNING" +- id: python_crypto_rule-hash-sha1 + languages: + - "python" + message: | + The application was found using an insecure or risky digest or signature algorithm. MD2, MD4, + MD5 and SHA1 hash algorithms have been found to be vulnerable to producing collisions. + + This means + that two different values, when hashed, can lead to the same hash value. If the application is + trying + to use these hash methods for storing passwords, then it is recommended to switch to a + password hashing + algorithm such as Argon2id or PBKDF2. + + Note that the `Crypto` and `Cryptodome` Python packages are no longer recommended for + new applications, instead consider using the [cryptography](https://cryptography.io/) package. + + Example of creating a SHA-384 hash using the `cryptography` package: + ``` + from cryptography.hazmat.primitives import hashes + # Create a SHA384 digest + digest = hashes.Hash(hashes.SHA384()) + # Update the digest with some initial data + digest.update(b"some data to hash") + # Add more data to the digest + digest.update(b"some more data") + # Finalize the digest as bytes + result = digest.finalize() + ``` + + For more information on secure password storage see OWASP: + - https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html + + For more information on the cryptography module see: + - https://cryptography.io/en/latest/ + metadata: + cwe: "CWE-327" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + category: "security" + shortDescription: "Use of a broken or risky cryptographic algorithm" + security-severity: "Medium" + pattern: "hashlib.sha1(...)" + severity: "WARNING" +- id: python_crypto_rule-hashlib-new-insecure-functions + languages: + - "python" + message: | + The application was found using an insecure or risky digest or signature algorithm. MD2, MD4, + MD5 and SHA1 hash algorithms have been found to be vulnerable to producing collisions. + + This means + that two different values, when hashed, can lead to the same hash value. If the application is + trying + to use these hash methods for storing passwords, then it is recommended to switch to a + password hashing + algorithm such as Argon2id or PBKDF2. + It is strongly recommended that a standard digest algorithm be chosen instead as implementing + a custom algorithm is prone to errors. + + Example using `hashlib.sha384()` to create a SHA384 hash: + ``` + import hashlib + # Create a SHA384 digest + digest = hashlib.sha384() + # Update the digest with some initial data + digest.update(b"some data to hash") + # Add more data to the digest + digest.update(b"some more data") + # Finalize the digest as bytes + digest.digest() + ``` + metadata: + cwe: "CWE-327" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + category: "security" + shortDescription: "Use of a broken or risky cryptographic algorithm" + security-severity: "Medium" + patterns: + - pattern-either: + - pattern: "hashlib.new(\"=~/[M|m][D|d][4|5]/\", ...)" + - pattern: "hashlib.new(..., name=\"=~/[M|m][D|d][4|5]/\", ...)" + - pattern: "hashlib.new('sha1')" + - pattern: "hashlib.new(..., name='SHA1')" + - pattern: "hashlib.new('sha', string='test')" + - pattern: "hashlib.new(name='SHA', string='test')" + severity: "WARNING" +- id: python_crypto_rule-import-pycrypto + languages: + - "python" + message: | + The application was detected importing `pycrypto`. This package has been deprecated as it + contains + security vulnerabilities. + + To remediate this issue, consider using the [cryptography](https://cryptography.io/) + package instead. + metadata: + cwe: "CWE-1104" + owasp: + - "A9:2017-Using Components with Known Vulnerabilities" + - "A02:2021-Cryptographic Failures" + category: "security" + shortDescription: "Use of unmaintained third party components" + security-severity: "Medium" + pattern-either: + - pattern: "import pycryto" + - pattern: "import Crypto.Cipher" + - pattern: "import Crypto.Hash" + - pattern: "import Crypto.IO" + - pattern: "import Crypto.Protocol" + - pattern: "import Crypto.PublicKey" + - pattern: "import Crypto.Random" + - pattern: "import Crypto.Signature" + - pattern: "import Crypto.Util" + severity: "ERROR" +- id: python_deserialization_rule-cpickle + languages: + - "python" + message: | + The application was found using `cPickle` which is vulnerable to deserialization attacks. + Deserialization attacks exploit the process of reading serialized data and turning it back + into an object. By constructing malicious objects and serializing them, an adversary may + attempt to: + + - Inject code that is executed upon object construction, which occurs during the + deserialization process. + - Exploit mass assignment by including fields that are not normally a part of the serialized + data but are read in during deserialization. + + Consider safer alternatives such as serializing data in the JSON format. Ensure any format + chosen allows + the application to specify exactly which object types are allowed to be deserialized. + + To protect against mass assignment, only allow deserialization of the specific fields that are + required. If this is not easily done, consider creating an intermediary type that + can be serialized with only the necessary fields exposed. + + Example JSON deserializer using an intermediary type that is validated against a schema to + ensure + it is safe from mass assignment: + ``` + import jsonschema + + # Create a schema to validate our user-supplied input against + # an intermediary object + intermediary_schema = { + "type" : "object", + "properties" : { + "name": {"type" : "string"} + }, + "required": ["name"], + # Protect against random properties being added to the object + "additionalProperties": False, + } + # If a user attempted to add "'is_admin': True" it would cause a validation error + intermediary_object = {'name': 'test user'} + + try: + # Validate the user supplied intermediary object against our schema + jsonschema.validate(instance=intermediary_object, schema=intermediary_schema) + user_object = {'user': + { + # Assign the deserialized data from intermediary object + 'name': intermediary_object['name'], + # Add in protected data in object definition (or set it from a class constructor) + 'is_admin': False, + } + } + # Work with the user_object + except jsonschema.exceptions.ValidationError as ex: + # Gracefully handle validation errors + # ... + ``` + + For more details on deserialization attacks in general, see OWASP's guide: + - https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html + metadata: + cwe: "CWE-502" + owasp: + - "A8:2017-Insecure Deserialization" + - "A08:2021-Software and Data Integrity Failures" + category: "security" + shortDescription: "Deserialization of untrusted data" + security-severity: "High" + pattern: "cPickle.$FUNC(...)" + severity: "WARNING" +- id: python_deserialization_rule-dill + languages: + - "python" + message: | + The application was found using `dill` which is vulnerable to deserialization attacks. + Deserialization attacks exploit the process of reading serialized data and turning it back + into an object. By constructing malicious objects and serializing them, an adversary may + attempt to: + + - Inject code that is executed upon object construction, which occurs during the + deserialization process. + - Exploit mass assignment by including fields that are not normally a part of the serialized + data but are read in during deserialization. + + Consider safer alternatives such as serializing data in the JSON format. Ensure any format + chosen allows + the application to specify exactly which object types are allowed to be deserialized. + + To protect against mass assignment, only allow deserialization of the specific fields that are + required. If this is not easily done, consider creating an intermediary type that + can be serialized with only the necessary fields exposed. + + Example JSON deserializer using an intermediary type that is validated against a schema to + ensure + it is safe from mass assignment: + ``` + import jsonschema + + # Create a schema to validate our user-supplied input against + # an intermediary object + intermediary_schema = { + "type" : "object", + "properties" : { + "name": {"type" : "string"} + }, + "required": ["name"], + # Protect against random properties being added to the object + "additionalProperties": False, + } + # If a user attempted to add "'is_admin': True" it would cause a validation error + intermediary_object = {'name': 'test user'} + + try: + # Validate the user supplied intermediary object against our schema + jsonschema.validate(instance=intermediary_object, schema=intermediary_schema) + user_object = {'user': + { + # Assign the deserialized data from intermediary object + 'name': intermediary_object['name'], + # Add in protected data in object definition (or set it from a class constructor) + 'is_admin': False, + } + } + # Work with the user_object + except jsonschema.exceptions.ValidationError as ex: + # Gracefully handle validation errors + # ... + ``` + + For more details on deserialization attacks in general, see OWASP's guide: + - https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html + metadata: + cwe: "CWE-502" + owasp: + - "A8:2017-Insecure Deserialization" + - "A08:2021-Software and Data Integrity Failures" + category: "security" + shortDescription: "Deserialization of untrusted data" + security-severity: "High" + patterns: + - pattern: dill.$FUNC(...) + - pattern-not: dill.$FUNC("...") + severity: "WARNING" +- id: python_deserialization_rule-marshal + languages: + - "python" + message: | + The application was found using `dill` which is vulnerable to deserialization attacks. + Deserialization attacks exploit the process of reading serialized data and turning it back + into an object. By constructing malicious objects and serializing them, an adversary may + attempt to: + + - Inject code that is executed upon object construction, which occurs during the + deserialization process. + - Exploit mass assignment by including fields that are not normally a part of the serialized + data but are read in during deserialization. + + Consider safer alternatives such as serializing data in the JSON format. Ensure any format + chosen allows + the application to specify exactly which object types are allowed to be deserialized. + + To protect against mass assignment, only allow deserialization of the specific fields that are + required. If this is not easily done, consider creating an intermediary type that + can be serialized with only the necessary fields exposed. + + Example JSON deserializer using an intermediary type that is validated against a schema to + ensure + it is safe from mass assignment: + ``` + import jsonschema + + # Create a schema to validate our user-supplied input against + # an intermediary object + intermediary_schema = { + "type" : "object", + "properties" : { + "name": {"type" : "string"} + }, + "required": ["name"], + # Protect against random properties being added to the object + "additionalProperties": False, + } + # If a user attempted to add "'is_admin': True" it would cause a validation error + intermediary_object = {'name': 'test user'} + + try: + # Validate the user supplied intermediary object against our schema + jsonschema.validate(instance=intermediary_object, schema=intermediary_schema) + user_object = {'user': + { + # Assign the deserialized data from intermediary object + 'name': intermediary_object['name'], + # Add in protected data in object definition (or set it from a class constructor) + 'is_admin': False, + } + } + # Work with the user_object + except jsonschema.exceptions.ValidationError as ex: + # Gracefully handle validation errors + # ... + ``` + + For more details on deserialization attacks in general, see OWASP's guide: + - https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html + metadata: + cwe: "CWE-502" + owasp: + - "A8:2017-Insecure Deserialization" + - "A08:2021-Software and Data Integrity Failures" + category: "security" + shortDescription: "Deserialization of untrusted data" + security-severity: "High" + pattern-either: + - pattern: "marshal.dump(...)" + - pattern: "marshal.dumps(...)" + - pattern: "marshal.load(...)" + - pattern: "marshal.loads(...)" + severity: "WARNING" +- id: python_deserialization_rule-pickle + languages: + - "python" + message: | + The application was found using `pickle` which is vulnerable to deserialization attacks. + Deserialization attacks exploit the process of reading serialized data and turning it back + into an object. By constructing malicious objects and serializing them, an adversary may + attempt to: + + - Inject code that is executed upon object construction, which occurs during the + deserialization process. + - Exploit mass assignment by including fields that are not normally a part of the serialized + data but are read in during deserialization. + + Consider safer alternatives such as serializing data in the JSON format. Ensure any format + chosen allows the application to specify exactly which object types are allowed to be deserialized. + + To protect against mass assignment, only allow deserialization of the specific fields that are + required. If this is not easily done, consider creating an intermediary type that + can be serialized with only the necessary fields exposed. + + Example JSON deserializer using an intermediary type that is validated against a schema to ensure + it is safe from mass assignment: + ``` + import jsonschema + + # Create a schema to validate our user-supplied input against + # an intermediary object + intermediary_schema = { + "type" : "object", + "properties" : { + "name": {"type" : "string"} + }, + "required": ["name"], + # Protect against random properties being added to the object + "additionalProperties": False, + } + # If a user attempted to add "'is_admin': True" it would cause a validation error + intermediary_object = {'name': 'test user'} + + try: + # Validate the user supplied intermediary object against our schema + jsonschema.validate(instance=intermediary_object, schema=intermediary_schema) + user_object = {'user': + { + # Assign the deserialized data from intermediary object + 'name': intermediary_object['name'], + # Add in protected data in object definition (or set it from a class constructor) + 'is_admin': False, + } + } + # Work with the user_object + except jsonschema.exceptions.ValidationError as ex: + # Gracefully handle validation errors + # ... + ``` + + For more details on deserialization attacks in general, see OWASP's guide: + - https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html + metadata: + cwe: "CWE-502" + owasp: + - "A8:2017-Insecure Deserialization" + - "A08:2021-Software and Data Integrity Failures" + category: "security" + shortDescription: "Deserialization of untrusted data" + security-severity: "High" + patterns: + - pattern-either: + - patterns: + - pattern: "pickle.$METHOD(...)" + - pattern-not: "pickle.$METHOD(\"...\")" + - patterns: + - pattern: "_pickle.$METHOD(...)" + - pattern-not: "_pickle.$METHOD(\"...\")" + - metavariable-regex: + metavariable: "$METHOD" + regex: "(load|loads|Unpickler)" + severity: "WARNING" +- id: python_deserialization_rule-shelve + languages: + - "python" + message: | + The application was found using `shelve` which is vulnerable to deserialization attacks as + it calls `pickle` internally. + Deserialization attacks exploit the process of reading serialized data and turning it back + into an object. By constructing malicious objects and serializing them, an adversary may + attempt to: + + - Inject code that is executed upon object construction, which occurs during the + deserialization process. + - Exploit mass assignment by including fields that are not normally a part of the serialized + data but are read in during deserialization. + + Consider safer alternatives such as serializing data in the JSON format. Ensure any format + chosen allows + the application to specify exactly which object types are allowed to be deserialized. + + To protect against mass assignment, only allow deserialization of the specific fields that are + required. If this is not easily done, consider creating an intermediary type that + can be serialized with only the necessary fields exposed. + + Example JSON deserializer using an intermediary type that is validated against a schema to + ensure + it is safe from mass assignment: + ``` + import jsonschema + + # Create a schema to validate our user-supplied input against + # an intermediary object + intermediary_schema = { + "type" : "object", + "properties" : { + "name": {"type" : "string"} + }, + "required": ["name"], + # Protect against random properties being added to the object + "additionalProperties": False, + } + # If a user attempted to add "'is_admin': True" it would cause a validation error + intermediary_object = {'name': 'test user'} + + try: + # Validate the user supplied intermediary object against our schema + jsonschema.validate(instance=intermediary_object, schema=intermediary_schema) + user_object = {'user': + { + # Assign the deserialized data from intermediary object + 'name': intermediary_object['name'], + # Add in protected data in object definition (or set it from a class constructor) + 'is_admin': False, + } + } + # Work with the user_object + except jsonschema.exceptions.ValidationError as ex: + # Gracefully handle validation errors + # ... + ``` + + For more details on deserialization attacks in general, see OWASP's guide: + - https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html + metadata: + cwe: "CWE-502" + owasp: + - "A8:2017-Insecure Deserialization" + - "A08:2021-Software and Data Integrity Failures" + category: "security" + shortDescription: "Deserialization of untrusted data" + security-severity: "High" + pattern-either: + - pattern: "shelve.$FUNC(...)" + severity: "WARNING" +- id: python_deserialization_rule-yaml-load + languages: + - "python" + message: | + The application was found using an unsafe version of `yaml` load which is vulnerable to + deserialization attacks. Deserialization attacks exploit the process of reading serialized + data and turning it back + into an object. By constructing malicious objects and serializing them, an adversary may + attempt to: + + - Inject code that is executed upon object construction, which occurs during the + deserialization process. + - Exploit mass assignment by including fields that are not normally a part of the serialized + data but are read in during deserialization. + + To remediate this issue, use `safe_load()` or call `yaml.load()` with the `Loader` argument + set to + `yaml.SafeLoader`. + + Example loading YAML using `safe_load`: + ``` + import yaml + + # Use safe_load to load data into an intermediary object + intermediary_object = yaml.safe_load("""user: + name: 'test user'""" + ) + # Create our real object, copying over only the necessary fields + user_object = {'user': { + # Assign the deserialized data from intermediary object + 'name': intermediary_object['user']['name'], + # Add in protected data in object definition (or set it from a class constructor) + 'is_admin': False, + } + } + # Work with user_object + # ... + ``` + + For more details on deserialization attacks in general, see OWASP's guide: + - https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html + patterns: + - pattern-inside: | + import yaml + ... + - pattern-not-inside: | + from ruamel.yaml import YAML + ... + - pattern-either: + - pattern: "yaml.unsafe_load(...)" + - pattern: "yaml.$LD(..., Loader=yaml.$LOADER, ...)" + - pattern: "yaml.$LD($DATA)" + - metavariable-regex: + metavariable: "$LOADER" + regex: "(Loader|UnsafeLoader|CLoader|FullLoader)" + - metavariable-regex: + metavariable: "$LD" + regex: "(load|load_all)" + metadata: + cwe: "CWE-502" + owasp: + - "A8:2017-Insecure Deserialization" + - "A08:2021-Software and Data Integrity Failures" + category: "security" + shortDescription: "Deserialization of untrusted data" + security-severity: "High" + severity: "ERROR" +- id: python_django_rule-django-extra-used + languages: + - "python" + message: | + SQL Injection is a critical vulnerability that can lead to data or system compromise. By + dynamically generating SQL query strings, user input may be able to influence the logic of + the SQL statement. This could lead to an adversary accessing information they should + not have access to, or in some circumstances, being able to execute OS functionality or code. + + Replace all dynamically generated SQL queries with parameterized queries. In situations where + dynamic queries must be created, never use direct user input, but instead use a map or + dictionary of valid values and resolve them using a user supplied key. + + For example, some database drivers do not allow parameterized queries for `>` or `<` comparison + operators. In these cases, do not use a user supplied `>` or `<` value, but rather have the + user + supply a `gt` or `lt` value. The alphabetical values are then used to look up the `>` and `<` + values to be used in the construction of the dynamic query. The same goes for other queries + where + column or table names are required but cannot be parameterized. + + The `QuerySet.extra` API method will be deprecated as it a source of SQL Injection + vulnerabilities and other problems. This method is especially risky as callers + will need to do their own escaping of any parameters that come from user-supplied + information. + + To remediate this issue, do not use `extra` but use other `QuerySet` methods to achieve + the same goals. If for some reason this is not feasible, consider using the `RawSQL` method + and making sure that all arguments, including user-supplied ones, are only used in + `params` + + + While not recommended due to [potential SQL + Injection](https://docs.djangoproject.com/en/4.2/ref/models/expressions/#raw-sql-expressions), + below is an example using `RawSQL`, + passing in user-supplied data as a `param` which will escape the input: + ``` + # If dealing with integer based user input, restrict the values to integers only using the + # path configuration: path('/someview/', views.some_view, + name='someview'), + + # views.py + def some_view(request, user_supplied_id): + # Never use string interpolation in the `sql` parameter. + # Never quote the `%s` string format such as `... where id='%s'` as this could lead to SQL + Injection. + # Pass the user supplied data only in the `params` parameter. + for obj in DBObject.objects.all().annotate( + val=RawSQL(sql="select id from some_secondary_table where id=%s", + params=[user_supplied_id])): + # Work with the results from the query + # ... + ``` + + For more information on QuerySet see: + - https://docs.djangoproject.com/en/4.2/ref/models/querysets/#queryset-api + + For more information on SQL Injection see OWASP: + - https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html + patterns: + - pattern: "$X.objects. ... .extra(..., $K = $V, ...)" + - pattern-not-inside: | + $V = ['...'] + ... + - metavariable-pattern: + metavariable: "$V" + patterns: + - pattern: "$V" + - pattern-not: "[..., '...', ...]" + - pattern-not: "{..., '...': '...', ...}" + - pattern-not: "\"...\"" + - pattern-not: "[..., \"...\" % \"...\", ...]" + - pattern-not: "{..., $L: \"...\" % \"...\", ...}" + - pattern-not: "{..., $L: \"...\".format(\"...\"), ...}" + - pattern-not: "[..., \"...\".format(\"...\"), ...]" + metadata: + cwe: "CWE-89" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + category: "security" + shortDescription: "Improper neutralization of special elements used in an SQL + Command ('SQL Injection')" + security-severity: "High" + severity: "WARNING" +- id: python_escaping_rule-jinja2-autoescape-false + languages: + - "python" + message: | + The application was found using Jinja2 `Environment` without autoescaping enabled. If using in + the context of HTML this could lead to Cross-Site Scripting (XSS) attacks when rendering with + user-supplied input. + + Unfortunately, Jinja2 does not support context-aware escaping, meaning it is insufficient to + protect against + XSS for the various web contexts. It is important to encode the data depending on the specific + context + it + is used in. There are at least six context types: + + - Inside HTML tags `
context 1
` + - Inside attributes: `
` + - Inside event attributes `` + - Inside script blocks: `` + - Unsafe element HTML assignment: `element.innerHTML = "context 5"` + - Inside URLs: `link` + + Script blocks alone have multiple ways they need to be encoded. Extra care must be taken if + user input + is ever output inside of script tags. + + User input that is displayed within the application must be encoded, sanitized or validated + to ensure it cannot be treated as HTML or executed as Javascript code. Care must also be + taken + to not mix server-side templating with client-side templating, as the server-side templating + will + not encode things like {{ 7*7 }} which may execute client-side templating features. + + It is _NOT_ advised to encode user input prior to inserting into a data store. The data will + need to be + encoded depending on context of where it is output. It is much safer to force the displaying + system to + handle the encoding and not attempt to guess how it should be encoded. + + To handle different contexts, one approach would be to write custom Jinja2 filters. Below is + an example + that escapes or encodes links and potentially malicious script, note this does not include + other contexts + such as CSS or attributes: + ``` + from jinja2 import Environment, select_autoescape, FileSystemLoader + from jinja2 import pass_eval_context + from markupsafe import Markup, escape + + @pass_eval_context + def escape_link(eval_ctx, value): + bad_link = "#JinjatmplZ" + # Block any values that start with // as that could be used to inject + # links to third party pages see: + https://en.wikipedia.org/wiki/Wikipedia:Protocol-relative_URL + if value.startswith('//'): + return bad_link + + # Only allow relative links + # if you want to allow links that start with http or ws replace with below: + # if not value.startswith('/'): and not value.startswith('http') and not + value.startswith('ws') + if not value.startswith('/'): + return bad_link + + # Alternatively, you could only call escape if autoescape is true + # if eval_ctx.autoescape: + # return escape(value) + # else + # return value + + return escape(value) + + # Create a replacement table + js_replacement = str.maketrans({ + '"': "\\u0022", + '`': "\\u0060", + '&': "\\u0026", + '\'': "\\u0027", + '+': "\\u002b", + '/': "\\/", + '<': "\\u003c", + '>': "\\u003e", + '\\': "\\\\", + '(': "\\u0028", + ')': "\\u0029", + }) + + @pass_eval_context + def escape_js(eval_ctx, value): + """ + Escape the input for use in ", + script_context="alert(1);alert`1`",) + ) + + # Sample template: + """ + + + + My Webpage + + +

My Webpage

+ {{ html_context }} + link + + + + """ + ``` + + For more information on autoescape see: + - https://jinja.palletsprojects.com/en/3.1.x/api/#autoescaping + + For more information on XSS see OWASP: + - https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html + metadata: + cwe: "CWE-116" + owasp: + - "A7:2017-Cross-Site Scripting (XSS)" + - "A03:2021-Injection" + category: "security" + shortDescription: "Improper encoding or escaping of output" + security-severity: "Medium" + patterns: + - pattern-inside: | + import jinja2 + ... + - pattern-not: "jinja2.Environment(..., autoescape=True, ...)" + - pattern-not: "jinja2.Environment(..., autoescape=jinja2.select_autoescape(...),...)" + - pattern-not: "jinja2.Environment(..., autoescape=select_autoescape(...), ...)" + - pattern: "jinja2.Environment(...)" + severity: "WARNING" +- id: python_escaping_rule-use-of-mako-templates + languages: + - "python" + message: | + The application was found using mako templates without `default_filters` + being passed to the `Template` or `TemplateLookup` constructors. If using + in the context of HTML, this could lead to Cross-Site Scripting (XSS) attacks + when rendering with user-supplied input. + + Unfortunately, Jinja2 does not support context-aware escaping, meaning it + is insufficient to protect against XSS for the various web contexts. It is + important to encode the data depending on the specific context it is used in. + There are at least six context types: + + - Inside HTML tags `
context 1
` + - Inside attributes: `
` + - Inside event attributes `` + - Inside script blocks: `` + - Unsafe element HTML assignment: `element.innerHTML = "context 5"` + - Inside URLs: + `link` + + Script blocks alone have multiple ways they need to be encoded. Extra care + must be taken if user input is ever output inside of script tags. + + User input that is displayed within the application must be encoded, + sanitized or validated to ensure it cannot be treated as HTML or executed + as Javascript code. Care must also be taken to not mix server-side templating + with client-side templating, as the server-side templating will not encode things + like {{ 7*7 }} which may execute client-side templating features. + + It is _NOT_ advised to encode user input prior to inserting into a data + store. The data will need to be encoded depending on context of where it is output. + It is much safer to force the displaying system to handle the encoding and + not attempt to guess how it should be encoded. + + To handle different contexts, one approach would be to write custom mako + filters. Below is an example that escapes or encodes links and + potentially malicious script, note this does not include other contexts + such as CSS or attributes: + ``` + # filters.py module: + + def escape_link(value): + bad_link = "#JinjatmplZ" + # Block any values that start with // as that could be used to inject + # links to third party pages see: + https://en.wikipedia.org/wiki/Wikipedia:Protocol-relative_URL + if value.startswith('//'): + return bad_link + + # Only allow relative links + # if you want to allow links that start with http or ws replace with below: + # if not value.startswith('/'): and not value.startswith('http') and not + value.startswith('ws') + if not value.startswith('/'): + return bad_link + + return value + + # Create a replacement table + js_replacement = str.maketrans({ + '\0': "\\u0000", + '\t': "\\t", + '\n': "\\n", + '\v': "\\u000b", + '\f': "\\f`", + '\r': "\\r", + '"': "\\u0022", + '`': "\\u0060", + '&': "\\u0026", + '\'': "\\u0027", + '+': "\\u002b", + '/': "\\/", + '<': "\\u003c", + '>': "\\u003e", + '\\': "\\\\", + '(': "\\u0028", + ')': "\\u0029", + }) + + def escape_js(value): + # Escape the input for use in + + + """ + + # Load our template with default filters and our imported filters for + # usage in template files + t = Template(template_text, + # By default enable the html filter with 'h' + default_filters=['h'], + # Import our custom filters + imports=["from filters import escape_link, escape_js"]) + + # Render our template + print(t.render(html_context="", + link_context="/# onclick=alert(1)", + script_context="alert(1)",) + ) + ``` + metadata: + cwe: "CWE-79" + category: "security" + owasp: + - "A7:2017-Cross-Site Scripting (XSS)" + - "A03:2021-Injection" + shortDescription: "Improper neutralization of input during web page generation ('Cross-site Scripting')" + security-severity: "Medium" + patterns: + - pattern-either: + - pattern: "mako.template.Template(...)" + - pattern: "mako.lookup.TemplateLookup(...)" + - pattern-not: "mako.lookup.TemplateLookup(..., default_filters=[\"...\"])" + - pattern-not: "mako.template.Template(..., default_filters=[\"...\"])" + severity: "WARNING" +- id: python_eval_rule-eval + languages: + - "python" + message: | + The application was found calling the `eval` function with non-literal data. If the variable contains + user-controlled data, either partially or fully, an adversary could compromise the entire system by + executing arbitrary Python code. + + To remediate this issue, remove all calls to `eval` and consider alternative methods for executing + the necessary business logic. There is almost no safe method of calling `eval` with user-supplied input. + + If the application only needs to convert strings into objects, consider using `json.loads`. In + some cases `ast.literal_eval` is recommended, but this should be avoided as it can still suffer + from other issues such as the ability for malicious code to crash the python interpreter or application. + + Example using `json.loads`` to load in arbitrary data to create data structures: + ``` + # User supplied data as a blob of JSON + user_supplied_data = """{"user": "test", "metadata": [1,2,3]}""" + # Load the JSON + user_object = json.loads(user_supplied_data) + # Manually add protected properties _after_ loading, never before + user_object["is_admin"] = False + # Work with the object + ``` + patterns: + - pattern: "eval($X,...)" + - pattern-not: | + eval("...") + - pattern-not: | + eval("..." % <... "..." ...>) + - pattern-not: | + eval(<... "...".format( "..." ) ...>) + - pattern-not-inside: | + def eval(...): + ... + ... + metadata: + cwe: "CWE-95" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + category: "security" + shortDescription: "Improper neutralization of directives in dynamically evaluated + code ('Eval Injection')" + security-severity: "High" + severity: "WARNING" +- id: python_exec_rule-exec-used + languages: + - "python" + message: | + The application was found calling the `exec` function with a non-literal variable. If the + variable comes from user-supplied input, an adversary could compromise the entire system by + executing arbitrary python code. + + To remediate this issue, remove all calls to `exec` and consider alternative methods for + executing the necessary business logic. There is almost no safe method of calling `eval` + with user-supplied input. + + If the application only needs to convert strings into objects, consider using `json.loads`. + In some cases `ast.literal_eval` is recommended, but this should be avoided as it can still + suffer from other issues such as the ability for malicious code to crash the python + interpreter or application. + + Example using `json.loads`` to load in arbitrary data to create data structures: + ``` + # User supplied data as a blob of JSON + user_supplied_data = """{"user": "test", "metadata": [1,2,3]}""" + # Load the JSON + user_object = json.loads(user_supplied_data) + # Manually add protected properties _after_ loading, never before + user_object["is_admin"] = False + # Work with the object + ``` + metadata: + cwe: "CWE-78" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + category: "security" + shortDescription: "Improper neutralization of special elements used in an OS command + ('OS Command Injection')" + security-severity: "High" + patterns: + - pattern: "exec(...)" + - pattern-not: "exec(\"...\")" + severity: "WARNING" +- id: python_exec_rule-os-path + languages: + - "python" + message: | + Starting a process with a shell; seems safe, but may be changed in the future, consider + rewriting without shell + pattern-either: + - pattern: "os.system(\"...\", ...)" + - pattern: "$OS.popen(\"...\", ...)" + - pattern: "$OS.popen2(\"...\", ...)" + - pattern: "$OS.popen3(\"...\", ...)" + - pattern: "$OS.popen4(\"...\", ...)" + - pattern: "commands.getoutput(\"...\", ...)" + - pattern: "commands.getstatusoutput(\"...\", ...)" + metadata: + cwe: "CWE-78" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + shortDescription: "Improper neutralization of special elements used in an OS Command + ('OS Command Injection')" + security-severity: "High" + category: "security" + severity: "INFO" +- id: python_exec_rule-os-popen2 + languages: + - "python" + message: | + Starting a process with a shell; seems safe, but may be changed in the future, consider + rewriting without shell + patterns: + - pattern-either: + - pattern: "os.system(...)" + - pattern: "os.popen(...)" + - pattern: "os.popen2(...)" + - pattern: "os.popen3(...)" + - pattern: "os.popen4(...)" + - pattern: "popen2.popen2(...)" + - pattern: "popen2.popen3(...)" + - pattern: "popen2.popen4(...)" + - pattern: "popen2.Popen3(...)" + - pattern: "popen2.Popen4(...)" + - pattern: "commands.getoutput(...)" + - pattern: "commands.getstatusoutput(\"\")" + metadata: + cwe: "CWE-78" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + shortDescription: "Improper neutralization of special elements used in an OS Command + ('OS Command Injection')" + security-severity: "High" + category: "security" + severity: "INFO" +- id: python_exec_rule-start-process-with-no-shell + languages: + - "python" + message: | + Found dynamic content when spawning a process. This is dangerous if externaldata can reach this + function call because it allows a malicious actor toexecute commands. Ensure no external data + reaches here. + patterns: + - pattern-either: + - patterns: + - pattern-not: "os.$W(\"...\", ...)" + - pattern-either: + - pattern: "os.execl(...)" + - pattern: "os.execle(...)" + - pattern: "os.execlp(...)" + - pattern: "os.execlpe(...)" + - pattern: "os.execv(...)" + - pattern: "os.execve(...)" + - pattern: "os.execvp(...)" + - pattern: "os.execvpe(...)" + - pattern: "os.startfile(...)" + - patterns: + - pattern-either: + - pattern: "os.spawnl(...)" + - pattern: "os.spawnle(...)" + - pattern: "os.spawnlp(...)" + - pattern: "os.spawnlpe(...)" + - pattern: "os.spawnv(...)" + - pattern: "os.spawnve(...)" + - pattern: "os.spawnvp(...)" + - pattern: "os.spawnvpe(...)" + metadata: + cwe: "CWE-78" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + shortDescription: "Improper neutralization of special elements used in an OS Command + ('OS Command Injection')" + security-severity: "High" + category: "security" + severity: "WARNING" +- id: python_exec_rule-subprocess-call + languages: + - "python" + message: | + Python possesses many mechanisms to invoke an external executable. However, + doing so may present a security issue if appropriate care is not taken to + sanitize any user provided or variable input. This plugin test is part of a + family of tests built to check for process spawning and warn appropriately. + Specifically, this test looks for the spawning of a subprocess without the + use of a command shell. This type of subprocess invocation is not + vulnerable to shell injection attacks, but care should still be taken to + ensure validity of input. + patterns: + - pattern-not: "subprocess.$FUNC($ARG, shell=<... True ...>)" + - pattern-not: "subprocess.$FUNC($ARG, shell=<... 'True' ...>)" + - pattern-not: "subprocess.$FUNC($ARG, shell=<... \"True\" ...>)" + - pattern-either: + - pattern: | + subprocess.$FUNC($ARG, shell=False) + - pattern: | + subprocess.$FUNC($ARG, shell=0) + - pattern: | + subprocess.$FUNC($ARG, shell={...}) + - pattern: | + subprocess.$FUNC($ARG, shell=[...]) + - pattern: | + subprocess.$FUNC($ARG) + metadata: + cwe: "CWE-78" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + shortDescription: "Improper neutralization of special elements used in an OS Command + ('OS Command Injection')" + security-severity: "High" + category: "security" + severity: "WARNING" +- id: python_exec_rule-subprocess-popen-shell-true + languages: + - "python" + patterns: + - patterns: + - pattern-not-inside: | + ... + $ARG = '...'.format('...') + ... + - pattern: "subprocess.$FUNC($ARG, ...)" + - pattern-not: "subprocess.$FUNC('...', ...)" + - pattern-not: "subprocess.$FUNC('...' % '...', ...)" + - pattern-not: "subprocess.$FUNC('...'.format('...'), ...)" + - pattern-either: + - pattern: "subprocess.$FUNC(..., shell=True, ...)" + - pattern: "subprocess.$FUNC(..., shell=[$V, ...], ...)" + - pattern: "subprocess.$FUNC(..., shell={$K: $V, ...}, ...)" + - patterns: + - pattern: "subprocess.$FUNC(..., shell=$INTVAL, ...)" + - pattern-not: "subprocess.$FUNC(..., shell=0, ...)" + - metavariable-regex: + metavariable: "$INTVAL" + regex: "^[0-9]+$" + - patterns: + - pattern: "subprocess.$FUNC(..., shell='$STRVAL', ...)" + - pattern-not: "subprocess.$FUNC(..., shell='', ...)" + message: | + Found `subprocess` function `$FUNC` with `shell=True`. This is dangerous because this call will + spawn the command using a shell process. Doing so propagates current shell settings and + variables, + which makes it much easier for a malicious actor to execute commands. Use `shell=False` + instead. + metadata: + cwe: "CWE-78" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + shortDescription: "Improper neutralization of special elements used in an OS Command + ('OS Command Injection')" + security-severity: "High" + category: "security" + severity: "ERROR" +- id: python_exec_rule-subprocess-shell-TRUE + languages: + - "python" + message: | + subprocess call - check for execution of untrusted input + patterns: + - pattern-not: "subprocess.$FUNC(..., shell=True, ...)" + - pattern: "$FOO(..., shell=True, ...)" + metadata: + cwe: "CWE-78" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + shortDescription: "Improper neutralization of special elements used in an OS Command + ('OS Command Injection')" + security-severity: "High" + category: "security" + severity: "WARNING" +- id: python_file-permissions_rule-general-bad-permission + languages: + - "python" + message: | + The application was found setting file permissions to overly permissive values. Consider + using the following values if the application user is the only process to access + the file: + + - 0400 - read only access to the file + - 0200 - write only access to the file + - 0600 - read/write access to the file + + Example creating a file with read/write permissions for the application user: + ``` + # Use octal values to set 0o600 (read/write access to the file) for the current + # user + os.chmod('somefile.txt', 0o600) + ``` + + For all other values please see: + https://en.wikipedia.org/wiki/File-system_permissions#Numeric_notation + metadata: + shortDescription: "Incorrect permission assignment for critical resource" + cwe: "CWE-732" + category: "security" + owasp: + - "A5:2017-Broken Access Control" + - "A01:2021-Broken Access Control" + security-severity: "Medium" + patterns: + - pattern: "os.chmod(...,$MASK)" + - metavariable-regex: + metavariable: "$MASK" + regex: "(0x..f|0o..[2,3,7]|stat.S_IXGRP|stat.S_IWOTH)" + severity: "WARNING" +- id: python_files_rule-tarfile-unsafe-members + languages: + - "python" + message: | + The application may be vulnerable to a path traversal if it extracts untrusted archive files. + This vulnerability is colloquially known as 'Zip Slip'. Archive files may contain folders + which, + when extracted, may write outside of the intended directory. This is exploited by including + path traversal characters such as `../../other/directory` to overwrite or place files in system + or application directories. + + Extra care must be taken when extracting archive files as there are numerous concerns: + + - If possible, generate unique filenames instead of using the archives file names, as it may be + possible for users to overwrite files if the filenames are the same. + - Validate file paths are written with a prefixed, known trusted directory. + - Only process regular files and not symbolic links, as some applications may attempt to + read/follow + the symbolic link, leading to arbitrary file read / write vulnerabilities. + + Example of securely processing an archive file: + ``` + import tarfile + import uuid + # import os + + tar = tarfile.open('some.tar') + + # Max number of allowed files in our archive + max_files = 10 + # Max size for all files in archive + max_size = 1024 * 1024 * 10 # 10MB + # Max size per file in archive + max_file_size = 1024 * 1024 # 1MB + + # Validate number of files in archive + if len(tar.getmembers()) > max_files: + raise Exception("Too many files in archive") + + total_size = 0 + # Loop over all files to see if we exceed max size + # if so, do not process any of them. + for f in tar.getmembers(): + total_size += f.size + if total_size >= max_size: + raise Exception("Archive files exceeded max file size") + + # Iterate over files now that we know the total size is within limits + for f in tar.getmembers(): + # Internally this calls TarInfo.isreg() which ensures + # the file is a regular file and not a sym link or directory + if not f.isfile(): + continue + + # Optional, set a limit on each file size + if f.size > max_file_size: + raise Exception(f"File {f.name} too large: {f.size}") + + # If original names are required, ensure that only the + # filename is used: + # filename = os.path.basename(f.name) + + # More secure, generate a UUID4 value instead + filename = uuid.uuid4().hex + + # Reset the archive filename to the basename + # Newer versions of python (3.11.4+) should use: + # new_tar = old_tar.replace(name=...new name...) + f.name = filename + + # Extract the file into a restricted directory, with our + # own user's attributes, not the file from the archive + tar.extract(f, '/opt/app/restricted/', set_attrs=False) + ``` + + For more information on tarfile see: + - https://docs.python.org/3/library/tarfile.html + metadata: + cwe: "CWE-22" + owasp: + - "A5:2017-Broken Access Control" + - "A01:2021-Broken Access Control" + shortDescription: "Improper limitation of a pathname to a restricted directory + ('Path Traversal')" + security-severity: "Medium" + category: "security" + patterns: + - pattern-inside: | + import tarfile + ... + - pattern-either: + - patterns: + - pattern-inside: | + $TAR = tarfile.open(...) + ... + - pattern-either: + - pattern: "$TAR.extractall(...)" + - pattern: "tarfile.extractall(..., members=$TAR)" + - pattern: "$TAR.extractall(..., members=[])" + - patterns: + - pattern: "tarfile.extractall(...)" + - pattern: "tarfile.extractall(..., members=[])" + severity: "WARNING" +- id: python_flask_rule-app-debug + languages: + - "python" + message: | + The Flask application is running with `debug=True` configured. By enabling this option, certain + exceptions or errors could cause sensitive information to be leaked in HTTP responses. + + Additionally, it is not recommended to run a Flask application using `Flask.run(...)` in + production. Instead, a WSGI server such as + [gunicorn](https://flask.palletsprojects.com/en/2.3.x/deploying/gunicorn/) + or [waitress](https://flask.palletsprojects.com/en/2.3.x/deploying/waitress/) be used instead. + + For more information on deployment options for Flask applications see: + - https://flask.palletsprojects.com/en/2.3.x/deploying/ + metadata: + cwe: "CWE-489" + category: "security" + owasp: + - "A6:2017-Security Misconfiguration" + - "A05:2021-Security Misconfiguration" + shortDescription: "Active debug code" + security-severity: "Medium" + patterns: + - pattern-inside: | + import flask + ... + - pattern: "$APP.run(..., debug=True, ...)" + severity: "WARNING" +- id: python_ftp_rule-ftplib + languages: + - "python" + message: | + The application was found using an FTP library. As FTP does not provide encryption, it is + strongly recommended that any file transfers be done over a more secure transport such as + SSH. + + The [paramiko](https://www.paramiko.org/) library can be used with an SCP module to allow + secure file transfers. + + Example using `paramiko` SSH client and the `scp` module: + ``` + import paramiko + import scp + + # Create an SSH client + with paramiko.SSHClient() as ssh: + # Load the system host keys so we can confirm the + # host we are connecting to is legitimate + ssh.load_system_host_keys('/home/appuser/.ssh/known_hosts') + + # Connect to the remote host using our SSH private key + ssh.connect(hostname='example.org', + port=22, + username='appuser', + key_filename='/home/appuser/.ssh/private_key') + + # Create an SCP client with the ssh transport and copy files + with scp.SCPClient(ssh.get_transport()) as secure_copy: + secure_copy.get('remote/test.file', 'local/test.file') + secure_copy.put('local/some.file', 'remote/some.file') + ``` + + For more information on the paramiko module see: + - https://www.paramiko.org/ + + For more information on the scp module see: + - https://github.com/jbardin/scp.py + metadata: + cwe: "CWE-319" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + category: "security" + shortDescription: "Cleartext transmission of sensitive information" + security-severity: "Medium" + pattern: "ftplib.$ANYTHING(...)" + severity: "WARNING" +- id: python_log_rule-logging-config-insecure-listen + languages: + - "python" + message: | + The application was found calling the `logging.config.listen`` function, which provides the + ability to listen for + external configuration files over a socket server. This listen socket parses part of the + configuration and calls + `eval` on the supplied configuration file. A local user, or an adversary who is able to + exploit + a Server Side Request Forgery (SSRF) attack to communicate over localhost, would be able to + execute arbitrary + code by passing in a logging config that contains python code. + + To remediate the issue, remove the call to `logging.config.listen` method. + + For more information on the listen functionality see: + - https://docs.python.org/3/library/logging.config.html#logging.config.listen + metadata: + cwe: "CWE-94" + shortDescription: "Improper control of generation of code ('Code Injection')" + category: "security" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "High" + patterns: + - pattern: "logging.config.listen(...)" + severity: "WARNING" +- id: python_random_rule-random + languages: + - "python" + message: | + Depending on the context, generating weak random numbers may expose cryptographic functions, + which rely on these numbers, to be exploitable. When generating numbers for sensitive values + such as tokens, nonces, and cryptographic keys, it is recommended that the `secrets` module + be used instead. + + Example using the secrets module: + ``` + import secrets + + # Generate a secure random 64 byte array + random_bytes = secrets.token_bytes(64) + print(random_bytes) + + # Generate a secure random 64 byte array as a hex string + random_bytes_hex = secrets.token_hex(64) + + # Generate a secure random 64 byte array base64 encoded for use in URLs + random_string = secrets.token_urlsafe(64) + ``` + + For more information on the `secrets` module see: + - https://docs.python.org/3/library/secrets.html + metadata: + cwe: "CWE-338" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + category: "security" + shortDescription: "Use of cryptographically weak pseudo-random number generator (PRNG)" + security-severity: "Low" + pattern-either: + - pattern: "random.random(...)" + - pattern: "random.randrange(...)" + - pattern: "random.randint(...)" + - pattern: "random.choice(...)" + - pattern: "random.uniform(...)" + - pattern: "random.triangular(...)" + severity: "WARNING" +- id: python_requests_rule-request-without-timeout + languages: + - "python" + message: | + The application was found using the `requests` module without configuring a timeout value for + connections. This could lead to uncontrolled resource consumption where the application could + run out of + socket descriptors, effectively causing a Denial of Service (DoS). + + To remediate this issue, pass in a `timeout=` argument to each `requests` call. + + Example using a timeout for an HTTP GET request: + ``` + # Issue a GET request to https://example.com with a timeout of 10 seconds + response = requests.get('https://example.com', timeout=10) + # Work with the response object + # ... + ``` + + For more information on using the requests module see: + - https://requests.readthedocs.io/en/latest/api/ + patterns: + - pattern-either: + - patterns: + - pattern: "requests.$METHOD(..., timeout=$VAL, ...)" + - metavariable-comparison: + comparison: "$VAL <= 0" + metavariable: "$VAL" + - patterns: + - pattern: "requests.$METHOD(..., timeout=$VAL, ...)" + - metavariable-regex: + metavariable: "$VAL" + regex: "(^None)" + - patterns: + - pattern-not: "requests.$METHOD(..., timeout=$VAL, ...)" + - pattern-either: + - pattern: "requests.$METHOD(..., ...)" + - pattern: "requests.$METHOD(...)" + - metavariable-regex: + metavariable: "$METHOD" + regex: "(get|put|delete|post|options|head|patch)" + metadata: + cwe: "CWE-770" + category: "security" + shortDescription: "Allocation of resources without limits or throttling" + owasp: + - "A6:2017-Security Misconfiguration" + - "A05:2021-Security Misconfiguration" + security-severity: "Medium" + severity: "WARNING" +- id: python_snmp_rule-insecure-snmp-version + languages: + - "python" + message: | + Pysnmp was detected using versions SNMPv1 or SNMPv2. SNPMv1 and SNMPv2 are insecure + and should no longer be used as they do not offer encryption. + + If possible, query SNMP devices using SNMPv3 instead. + + Example querying a device using SNMPv3 with SHA-AES: + ``` + from pysnmp.hlapi import * + # Create the snpm iterator + iterator = getCmd( + SnmpEngine(), + # Configure using SHA AES + UsmUserData('usr-sha-aes', 'authkey1', 'privkey1', + authProtocol=USM_AUTH_HMAC96_SHA, + privProtocol=USM_PRIV_CFB128_AES), + UdpTransportTarget(('demo.snmplabs.com', 161)), + ContextData(), + ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0)) + ) + ``` + + For more information on using SNMPv3 with `Pysnmp` see: + - https://pysnmp.readthedocs.io/en/latest/examples/hlapi/v3arch/asyncore/sync/manager/cmdgen/snmp-versions.html#snmpv3-auth-sha-privacy-aes128 + metadata: + cwe: "CWE-319" + category: "security" + shortDescription: "Cleartext transmission of sensitive information" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + security-severity: "Medium" + pattern-either: + - pattern: "pysnmp.hlapi.CommunityData(..., mpModel=0, ...)" + - pattern: "pysnmp.hlapi.CommunityData(..., mpModel=1, ...)" + severity: "WARNING" +- id: python_snmp_rule-snmp-weak-cryptography + languages: + - "python" + message: | + Pysnmp was detected using SNMPv3 without authentication or encryption + protections enabled. + + - Use of `usmNoAuthProtocol` or `usmNoPrivProtocol` indicates that + either authentication or privacy, respectively, is not being used. + - The absence of `authKey` (or `authKey=None`) implies no authentication, + which is equivalent to using `usmNoAuthProtocol`. + - The absence of `privKey` (or `privKey=None`) implies no privacy (encryption), + which is equivalent to using `usmNoPrivProtocol`. + + To enhance the security of your SNMP communications, it is recommended to use both + authentication and privacy features in SNMPv3: + + - Use SHA for Authentication: SHA (Secure Hash Algorithm) is a more secure option + for SNMP message authentication. To use SHA, set the `authProtocol` to + `usmHMACSHAAuthProtocol` and provide a strong `authKey`. + - Use AES for Privacy: AES (Advanced Encryption Standard) is recommended for + encrypting SNMP messages. Set the `privProtocol` to `usmAesCfb128Protocol` + or a similar AES-based protocol and specify a strong `privKey`. + + Example of secure `UsmUserData` configuration: + ``` + from pysnmp.hlapi import UsmUserData, usmHMACSHAAuthProtocol, usmAesCfb128Protocol + + user_data = UsmUserData('username','authKey', 'privKey', + authProtocol=usmHMACSHAAuthProtocol, + privProtocol=usmAesCfb128Protocol) + ``` + metadata: + cwe: "CWE-319" + category: "security" + shortDescription: "Cleartext transmission of sensitive information" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + security-severity: "Medium" + pattern-either: + - pattern-regex: "UsmUserData(.*usmNoAuthProtocol.*)" + - pattern-regex: "UsmUserData(.*usmNoPrivProtocol.*)" + - pattern: | + UsmUserData(..., authKey=None, ...) + - pattern: | + UsmUserData(..., privKey=None, ...) + - pattern: | + UsmUserData(..., authProtocol=(1,3,6,1,6,3,10,1,1,1), ...) + - pattern: | + UsmUserData(..., privProtocol=(1,3,6,1,6,3,10,1,2,1), ...) + - patterns: + - pattern-not: | + UsmUserData($NAME,$AUTHKEY,"...", ...) + - pattern-not: | + UsmUserData(..., privKey=$PRIVKEY, ...) + - pattern-not: | + UsmUserData(..., privProtocol=$PRIVPROT, ...) + - pattern: | + UsmUserData(...) + severity: "WARNING" +- id: python_sql_rule-hardcoded-sql-expression + languages: + - "python" + message: | + SQL Injection is a critical vulnerability that can lead to data or system compromise. By + dynamically generating SQL query strings, user input may be able to influence the logic of + the SQL statement. This could lead to an adversary accessing information they should + not have access to, or in some circumstances, being able to execute OS functionality or code. + + Replace all dynamically generated SQL queries with parameterized queries. In situations where + dynamic queries must be created, never use direct user input, but instead use a map or + dictionary of valid values and resolve them using a user supplied key. + + For example, some database drivers do not allow parameterized queries for `>` or `<` comparison + operators. In these cases, do not use a user supplied `>` or `<` value, but rather have the + user + supply a `gt` or `lt` value. The alphabetical values are then used to look up the `>` and `<` + values to be used in the construction of the dynamic query. The same goes for other queries + where + column or table names are required but cannot be parameterized. + + Example using `PreparedStatement` queries: + ``` + import sqlite3 + + # Create a new database (in memory) + con = sqlite3.connect(":memory:") + # Get a cursor from the connection + cur = con.cursor() + # Create a tuple of the value to be used in the parameterized query + params = ('user-input',) + # execute the statement, passing in the params for the value + cur.execute("select name from sqlite_master where name = ?", params) + # work with the result + result = cur.fetchall() + ``` + + For more information on SQL Injection see OWASP: + https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html + metadata: + cwe: "CWE-89" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + category: "security" + shortDescription: "Improper neutralization of special elements used in an SQL + Command ('SQL Injection')" + security-severity: "High" + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - pattern: | + "$QUERY" % ... + - pattern: | + "$QUERY".format(...) + - pattern: | + f"$QUERY{...}..." + - pattern: | + "$QUERY" + ... + - pattern: | + $TMP = "$QUERY" + ... + $SQL = $TMP + "..." % ... + - pattern: | + $SQL = "$QUERY" + ... + $SQL += ... + - metavariable-regex: + metavariable: $QUERY + regex: (?i)^(SELECT|INSERT|UPDATE|DELETE)\s + pattern-sinks: + - patterns: + - pattern: $DB.execute(...) + - pattern-not: + pattern-either: + - pattern: $DB.execute("...") + - pattern: $DB.execute("$QUERY" % "...") + - pattern: $DB.execute("$QUERY" + "...") + severity: "WARNING" +- id: python_ssh_rule-ssh-nohost-key-verification + languages: + - "python" + message: | + The application was found to ignore host keys. Host keys are important as + they provide assurance that the client can prove that the host is trusted. + By ignoring these host keys, it is impossible for the client to validate the + connection is to a trusted host. + + To remediate this issue, remove the call to `set_missing_host_key_policy(...)` which + sets the host key policy. Instead, load key files using either `load_system_host_keys` + or `load_host_keys` to only allow known good hosts. By not setting a host key policy + for unknown hosts, `paramiko`'s default policy is to use `RejectPolicy`. + + Example configuration connecting to a known, trusted host, and not allowing connections + to unknown hosts: + ``` + import paramiko + + # Create an SSH client + with paramiko.SSHClient() as ssh: + # Load the system host keys so we can confirm the + # host we are connecting to is legitimate + ssh.load_system_host_keys('/home/appuser/.ssh/known_hosts') + + # Connect to the remote host using our SSH private key + ssh.connect(hostname='example.org', + port=22, + username='appuser', + key_filename='/home/appuser/.ssh/private_key') + ``` + + For more information on `set_missing_host_key_policy` see: + - https://docs.paramiko.org/en/stable/api/client.html#paramiko.client.SSHClient.set_missing_host_key_policy + metadata: + cwe: "CWE-322" + category: "security" + owasp: + - "A5:2017-Broken Access Control" + - "A07:2021-Identification and Authentication Failures" + shortDescription: "Key exchange without entity authentication" + security-severity: "Medium" + patterns: + - pattern-inside: | + $CLIENT = paramiko.client.SSHClient(...) + ... + $CLIENT.set_missing_host_key_policy(...) + - pattern-either: + - pattern: "paramiko.client.AutoAddPolicy" + - pattern: "paramiko.client.WarningPolicy" + severity: "ERROR" +- id: python_ssl_rule-req-no-certvalid + languages: + - "python" + message: | + The application was found using the `requests` module without configuring a timeout value for + connections. The `verify=False` argument has been set, which effectively disables the + validation + of server certificates. + + This allows for an adversary who is in between the application and the target host to intercept + potentially sensitive information or transmit malicious data. + + To remediate this issue either remove the `verify=False` argument, or set `verify=True`to each + `requests` call. + + Example verifying server certificates for an HTTP GET request: + ``` + # Issue a GET request to https://example.com with a timeout of 10 seconds and verify the + # server certificate explicitly. + response = requests.get('https://example.com', timeout=10, verify=True) + # Work with the response object + # ... + ``` + + For more information on using the requests module see: + - https://requests.readthedocs.io/en/latest/api/ + metadata: + cwe: "CWE-295" + owasp: + - "A2:2017-Broken Authentication" + - "A07:2021-Identification and Authentication Failures" + category: "security" + shortDescription: "Improper certificate validation" + security-severity: "Medium" + patterns: + - pattern-either: + - pattern: "requests.put(..., verify=False, ...)" + - pattern: "requests.patch(..., verify=False, ...)" + - pattern: "requests.delete(..., verify=False, ...)" + - pattern: "requests.head(..., verify=False, ...)" + - pattern: "requests.options(..., verify=False, ...)" + - pattern: "requests.request(..., verify=False, ...)" + - pattern: "requests.get(..., verify=False, ...)" + - pattern: "requests.post(..., verify=False, ...)" + severity: "ERROR" +- id: python_ssl_rule-ssl-no-version + languages: + - "python" + message: | + The application was found calling `ssl.wrap_socket` without a TLS protocol version specified. + Additionally, `ssl.wrap_socket` has been deprecated since Python 3.7. It is strongly + recommended + that newer applications use TLS 1.2 or 1.3 and `SSLContext.wrap_socket`. + + To remediate this issue, create a new TLS context and pass in `ssl.PROTOCOL_TLS_CLIENT` + for clients or `ssl.PROTOCOL_TLS_SERVER` for servers to the `ssl.SSLContext(...)` `protocol=` + argument. When converting the socket to a TLS socket, use the new `SSLContext.wrap_socket` + method instead. + + + Example creating a TLS 1.3 client socket connection by using a newer version of Python + (3.11.4) and + the SSL module: + ``` + import ssl + import socket + + # Create our initial socket + with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock: + # Connect the socket + sock.connect(('www.example.org', 443)) + + # Create a new SSLContext with protocol set to ssl.PROTOCOL_TLS_CLIENT + # This will auto-select the highest grade TLS protocol version (1.3) + context = ssl.SSLContext(protocol=ssl.PROTOCOL_TLS_CLIENT) + # Load our a certificates for server certificate authentication + context.load_verify_locations('cert.pem') + # Create our TLS socket, and validate the server hostname matches + with context.wrap_socket(sock, server_hostname="www.example.org") as tls_sock: + # Send some bytes over the socket (HTTP request in this case)\ + data = bytes('GET / HTTP/1.1\r\nHost: example.org\r\n\r\n', 'utf-8') + sent_bytes = tls_sock.send(data) + # Validate number of sent bytes + # ... + # Read the response + resp = tls_sock.recv() + # Work with the response + # ... + ``` + + For more information on the ssl module see: + - https://docs.python.org/3/library/ssl.html + metadata: + cwe: "CWE-326" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + shortDescription: "Inadequate encryption strength" + security-severity: "Medium" + category: "security" + patterns: + - pattern: "ssl.wrap_socket()" + severity: "WARNING" +- id: python_ssl_rule-ssl-with-bad-version + languages: + - "python" + message: | + The application was found calling an SSL module with SSL or TLS protocols that have known + deficiencies. + It is strongly recommended that newer applications use TLS 1.2 or 1.3 and + `SSLContext.wrap_socket`. + + If using the `pyOpenSSL` module, please note that it has been deprecated and the Python + Cryptographic Authority + strongly suggests moving to use the [pyca/cryptography](https://github.com/pyca/cryptography) + module instead. + + To remediate this issue for the `ssl` module, create a new TLS context and pass in + `ssl.PROTOCOL_TLS_CLIENT` for clients or `ssl.PROTOCOL_TLS_SERVER` for servers to the + `ssl.SSLContext(...)` `protocol=` + argument. When converting the socket to a TLS socket, use the new `SSLContext.wrap_socket` + method instead. + + Example creating a TLS 1.3 client socket connection by using a newer version of Python + (3.11.4) and + the SSL module: + ``` + import ssl + import socket + + # Create our initial socket + with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock: + # Connect the socket + sock.connect(('www.example.org', 443)) + + # Create a new SSLContext with protocol set to ssl.PROTOCOL_TLS_CLIENT + # This will auto-select the highest grade TLS protocol version (1.3) + context = ssl.SSLContext(protocol=ssl.PROTOCOL_TLS_CLIENT) + # Load our a certificates for server certificate authentication + context.load_verify_locations('cert.pem') + # Create our TLS socket, and validate the server hostname matches + with context.wrap_socket(sock, server_hostname="www.example.org") as tls_sock: + # Send some bytes over the socket (HTTP request in this case)\ + data = bytes('GET / HTTP/1.1\r\nHost: example.org\r\n\r\n', 'utf-8') + sent_bytes = tls_sock.send(data) + # Validate number of sent bytes + # ... + # Read the response + resp = tls_sock.recv() + # Work with the response + # ... + ``` + + For more information on the ssl module see: + - https://docs.python.org/3/library/ssl.html + + For more information on pyca/cryptography and openssl see: + - https://cryptography.io/en/latest/openssl/ + metadata: + cwe: "CWE-326" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + shortDescription: "Inadequate Encryption Strength" + security-severity: "Medium" + category: "security" + patterns: + - pattern-either: + - pattern: "ssl.PROTOCOL_SSLv2" + - pattern: "ssl.PROTOCOL_SSLv3" + - pattern: "ssl.PROTOCOL_TLSv1" + - pattern: "ssl.PROTOCOL_TLSv1_1" + - pattern: "pyOpenSSL.SSL.SSLv2_METHOD" + - pattern: "pyOpenSSL.SSL.SSLv23_METHOD" + - pattern: "pyOpenSSL.SSL.SSLv3_METHOD" + - pattern: "pyOpenSSL.SSL.TLSv1_METHOD" + - pattern: "pyOpenSSL.SSL.TLSv1_1_METHOD" + severity: "ERROR" +- id: python_ssl_rule-unverified-context + languages: + - "python" + message: | + The application was found creating a SSL context using the `_create_unverified_context`. + This effectively disables the validation of server certificates. + + This allows for an adversary who is in between the application and the target host to intercept + potentially sensitive information or transmit malicious data. + + To remediate this issue remove the call to `_create_unverified_context` and either create a + default + context using `ssl.create_default_context` or create a context with TLS 1.3. + + Example creating a TLS 1.3 client socket connection by using a newer version of Python + (3.11.4) and + the SSL module: + ``` + import ssl + import socket + + # Create our initial socket + with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock: + # Connect the socket + sock.connect(('www.example.org', 443)) + + # Create a new SSLContext with protocol set to ssl.PROTOCOL_TLS_CLIENT + # This will auto-select the highest grade TLS protocol version (1.3) + context = ssl.SSLContext(protocol=ssl.PROTOCOL_TLS_CLIENT) + # Load our a certificates for server certificate authentication + context.load_verify_locations('cert.pem') + # Create our TLS socket, and validate the server hostname matches + with context.wrap_socket(sock, server_hostname="www.example.org") as tls_sock: + # Send some bytes over the socket (HTTP request in this case)\ + data = bytes('GET / HTTP/1.1\r\nHost: example.org\r\n\r\n', 'utf-8') + sent_bytes = tls_sock.send(data) + # Validate number of sent bytes + # ... + # Read the response + resp = tls_sock.recv() + # Work with the response + # ... + ``` + + Unverified SSL context detected. This will permit insecure connections without `verifyingSSL` + certificates. Use `ssl.create_default_context()` instead. + metadata: + cwe: "CWE-295" + owasp: + - "A2:2017-Broken Authentication" + - "A07:2021-Identification and Authentication Failures" + category: "security" + shortDescription: "Improper certificate validation" + security-severity: "Medium" + pattern: "ssl._create_unverified_context(...)" + severity: "ERROR" +- id: python_telnet_rule-import-telnib + languages: + - "python" + message: | + The application was found using a telnet library. As telnet does not provide encryption, it is + strongly recommended that communications use a more secure transport such as + SSH. + + The [paramiko](https://www.paramiko.org/) library can be used to initiate SSH connections. + + Example using `paramiko` SSH client: + ``` + import paramiko + import scp + + # Create an SSH client + with paramiko.SSHClient() as ssh: + # Load the system host keys so we can confirm the + # host we are connecting to is legitimate + ssh.load_system_host_keys('/home/appuser/.ssh/known_hosts') + + # Connect to the remote host using our SSH private key + ssh.connect(hostname='example.org', + port=22, + username='appuser', + key_filename='/home/appuser/.ssh/private_key') + # Work with the connection + ``` + + For more information on the paramiko module see: + - https://www.paramiko.org/ + metadata: + cwe: "CWE-319" + category: "security" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + shortDescription: "Cleartext transmission of sensitive information" + security-severity: "Medium" + patterns: + - pattern: "import telnetlib" + severity: "ERROR" +- id: python_tmpdir_rule-hardcodedtmp + languages: + - "python" + message: | + The application was found creating files in shared system temporary directories + (`/tmp` or `/var/tmp`) without using the `tempfile.TemporaryFile` function. Depending + on how the application uses this temporary file, an attacker may be able to create + symlinks that point to other files prior to the application creating or writing + to the target file, leading to unintended files being created or overwritten. + + Example using `tempfile.TemporaryFile` to write a file: + ``` + import tempfile + + # Open a new temporary file using a context manager + with tempfile.TemporaryFile() as fp: + # Write some data to the temporary file + fp.write(b'Some data') + # Seek back to beginning of file + fp.seek(0) + # Read it + data = fp.read() + # File is automatically closed/removed once we exit the with context + ``` + + For more information on alternative tempfile functions see: + - https://docs.python.org/3/library/tempfile.html + metadata: + cwe: "CWE-377" + category: "security" + shortDescription: "Insecure temporary file" + owasp: + - "A5:2017-Broken Access Control" + - "A01:2021-Broken Access Control" + security-severity: "Medium" + pattern: "$CALL(\"=~/^\\/tmp.*/\", ...)" + severity: "WARNING" +- id: python_tmpdir_rule-mktemp-q + languages: + - "python" + message: | + The application was found creating temporary files with the insecure `mktemp` method. + Depending on how the application uses this temporary file, an attacker may be able to create + symlinks that point to other files prior to the application creating or writing + to the target file, leading to unintended files being created or overwritten. + + To remediate this issue consider using `tempfile.TemporaryFile` instead. + + Example using `tempfile.TemporaryFile` to write a file: + ``` + import tempfile + + # Open a new temporary file using a context manager + with tempfile.TemporaryFile() as fp: + # Write some data to the temporary file + fp.write(b'Some data') + # Seek back to beginning of file + fp.seek(0) + # Read it + data = fp.read() + # File is automatically closed/removed once we exit the with context + ``` + + For more information on alternative tempfile functions see: + - https://docs.python.org/3/library/tempfile.html + metadata: + cwe: "CWE-377" + category: "security" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A01:2021-Broken Access Control" + shortDescription: "Insecure temporary file" + security-severity: "Medium" + pattern: "tempfile.mktemp(...)" + severity: "ERROR" +- id: python_urlopen_rule-urllib-urlopen + languages: + - "python" + message: | + The application was found passing in a non-literal value to the `urllib` methods which issue + requests. `urllib` supports the `file://` scheme, which may allow an adversary who can control + the URL value to read arbitrary files on the file system. + + To remediate this issue either hardcode the URLs being used in urllib or use the `requests` + module instead. + + Example using the `requests` module to issue an HTTPS request: + ``` + import requests + # Issue a GET request to https://example.com with a timeout of 10 seconds + response = requests.get('https://example.com', timeout=10) + # Work with the response object + # ... + ``` + patterns: + - pattern-either: + - patterns: + - pattern-either: + - pattern: "urllib.$METHOD(...)" + - pattern: "urllib.request.$METHOD(...)" + - pattern-not: "urllib.$METHOD(\"...\")" + - pattern-not: "urllib.request.$METHOD(\"...\")" + - pattern-not: "urllib.$METHOD(\"...\", ...)" + - pattern-not: "urllib.request.$METHOD(\"...\", ...)" + - metavariable-regex: + metavariable: "$METHOD" + regex: "(urlopen|urlretrieve)" + - patterns: + - pattern-either: + - pattern-inside: | + $OPENER = urllib.URLopener(...) + ... + - pattern-inside: | + $OPENER = urllib.request.URLopener(...) + ... + - pattern-inside: | + $OPENER = urllib.FancyURLopener(...) + ... + - pattern-inside: | + $OPENER = urllib.request.FancyURLopener(...) + ... + - pattern-either: + - pattern: "$OPENER.open(...)" + - pattern: "$OPENER.retrieve(...)" + - pattern-not: "$OPENER.open(\"...\")" + - pattern-not: "$OPENER.retrieve(\"...\")" + metadata: + cwe: "CWE-939" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + shortDescription: "Improper authorization in handler for custom URL scheme" + security-severity: "Medium" + category: "security" + severity: "WARNING" +- id: python_xml_rule-celement + languages: + - "python" + message: | + The application was found using the `xml.etree` package for processing XML. + Pythons default xml processors suffer from various XML parsing vulnerabilities + and care must be taken when handling XML data. Additionally, depending on the + version of Python, more critical vulnerabilities such as eXternal XML Entity + injection maybe exploitable. + + The `etree` package suffers from the following security risks as of Python 3.7.1: + * Billion laughs / exponential entity expansion - May allow an adversary to cause + a Denial of Service (DoS) against the application parsing arbitrary XML. + * Quadratic blowup entity expansion - Similar to above, but requires a larger input + to cause the Denial of Service. + + To remediate the above issues, consider using the + [defusedxml](https://pypi.org/project/defusedxml/) + library when processing untrusted XML. + + Example parsing an XML document using defusedxml: + ``` + from defusedxml.ElementTree import parse + + # Parse the inventory.xml file + et = parse('inventory.xml') + # Get the root element + root = et.getroot() + # Work with the root element + # ... + ``` + + For more information on the various XML parsers and their vulnerabilities please see: + - https://docs.python.org/3/library/xml.html#xml-vulnerabilities + + For more information on XML security see OWASP's guide: + - https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#python + metadata: + cwe: "CWE-611" + owasp: + - "A4:2017-XML External Entities (XXE)" + - "A03:2021-Injection" + category: "security" + shortDescription: "Improper restriction of XML external entity reference" + security-severity: "Medium" + pattern-either: + - patterns: + - pattern: "xml.etree.cElementTree.fromstring(...)" + - pattern-not: "xml.etree.cElementTree.fromstring(\"...\")" + - pattern: "xml.etree.cElementTree.parse(...)" + - pattern: "xml.etree.cElementTree.iterparse(...)" + - pattern: "xml.etree.cElementTree.XMLParser(...)" + severity: "WARNING" +- id: python_xml_rule-element + languages: + - "python" + message: | + The application was found using the `xml.etree` package for processing XML. + Pythons default xml processors suffer from various XML parsing vulnerabilities + and care must be taken when handling XML data. Additionally, depending on the + version of Python, more critical vulnerabilities such as eXternal XML Entity + injection maybe exploitable. + + The `etree` package suffers from the following security risks as of Python 3.7.1: + * Billion laughs / exponential entity expansion - May allow an adversary to cause + a Denial of Service (DoS) against the application parsing arbitrary XML. + * Quadratic blowup entity expansion - Similar to above, but requires a larger input + to cause the Denial of Service. + + To remediate the above issues, consider using the + [defusedxml](https://pypi.org/project/defusedxml/) + library when processing untrusted XML. + + Example parsing an XML document using defusedxml: + ``` + from defusedxml.ElementTree import parse + + # Parse the inventory.xml file + et = parse('inventory.xml') + # Get the root element + root = et.getroot() + # Work with the root element + # ... + ``` + + For more information on the various XML parsers and their vulnerabilities please see: + - https://docs.python.org/3/library/xml.html#xml-vulnerabilities + + For more information on XML security see OWASP's guide: + - https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#python + metadata: + cwe: "CWE-611" + owasp: + - "A4:2017-XML External Entities (XXE)" + - "A03:2021-Injection" + category: "security" + shortDescription: "Improper restriction of XML external entity reference" + security-severity: "Medium" + pattern-either: + - patterns: + - pattern: "xml.etree.ElementTree.fromstring(...)" + - pattern-not: "xml.etree.ElementTree.fromstring(\"...\")" + - pattern: "xml.etree.ElementTree.parse(...)" + - pattern: "xml.etree.ElementTree.iterparse(...)" + - pattern: "xml.etree.ElementTree.XMLParser(...)" + severity: "WARNING" +- id: python_xml_rule-etree + languages: + - "python" + message: | + The application was found using the `lxml.etree` package for processing XML. + Python's default XML processors suffer from various XML parsing vulnerabilities + and care must be taken when handling XML data. Additionally, depending on the + version of Python, more critical vulnerabilities such as eXternal XML Entity + injection maybe exploitable. + + The `etree` package suffers from the following security risks as of Python 3.7.1: + * Billion laughs / exponential entity expansion - May allow an adversary to cause + a Denial of Service (DoS) against the application parsing arbitrary XML. + * Quadratic blowup entity expansion - Similar to above, but requires a larger input + to cause the Denial of Service. + + To remediate the above issues, consider using the + [defusedxml](https://pypi.org/project/defusedxml/) + library when processing untrusted XML. + + Example parsing an XML document using defusedxml: + ``` + from defusedxml.ElementTree import parse + + # Parse the inventory.xml file + et = parse('inventory.xml') + # Get the root element + root = et.getroot() + # Work with the root element + # ... + ``` + + For more information on the various XML parsers and their vulnerabilities please see: + - https://docs.python.org/3/library/xml.html#xml-vulnerabilities + + For more information on XML security see OWASP's guide: + - https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#python + metadata: + cwe: "CWE-611" + owasp: + - "A4:2017-XML External Entities (XXE)" + - "A03:2021-Injection" + category: "security" + shortDescription: "Improper restriction of XML external entity reference" + security-severity: "Medium" + pattern-either: + - pattern: "lxml.etree.parse(...)" + - patterns: + - pattern: "lxml.etree.fromstring(...)" + - pattern-not: "lxml.etree.fromstring(\"...\")" + - pattern: "lxml.etree.RestrictedElement(...)" + - pattern: "lxml.etree.GlobalParserTLS(...)" + - pattern: "lxml.etree.getDefaultParser(...)" + - pattern: "lxml.etree.check_docinfo(...)" + severity: "WARNING" +- id: python_xml_rule-expatbuilder + languages: + - "python" + message: | + The application was found using the `xml.dom.expatbuilder` which calls the `xml.dom.minidom` + package for processing XML. Python's default XML processors suffer from various XML parsing + vulnerabilities + and care must be taken when handling XML data. Additionally, depending on the + version of Python, more critical vulnerabilities such as eXternal XML Entity + injection maybe exploitable. + + The `xml.dom.minidom` package suffers from the following security risks as of Python 3.7.1: + * Billion laughs / exponential entity expansion - May allow an adversary to cause + a Denial of Service (DoS) against the application parsing arbitrary XML. + * Quadratic blowup entity expansion - Similar to above, but requires a larger input + to cause the Denial of Service. + + To remediate the above issues, consider using the + [defusedxml](https://pypi.org/project/defusedxml/) + library when processing untrusted XML. + + Example parsing an XML document using defusedxml: + ``` + from defusedxml.ElementTree import parse + + # Parse the inventory.xml file + et = parse('inventory.xml') + # Get the root element + root = et.getroot() + # Work with the root element + # ... + ``` + + For more information on the various XML parsers and their vulnerabilities please see: + - https://docs.python.org/3/library/xml.html#xml-vulnerabilities + + For more information on XML security see OWASP's guide: + - https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#python + metadata: + cwe: "CWE-611" + owasp: + - "A4:2017-XML External Entities (XXE)" + - "A03:2021-Injection" + category: "security" + shortDescription: "Improper restriction of XML external entity reference" + security-severity: "Medium" + pattern-either: + - patterns: + - pattern: "xml.dom.expatbuilder.parse(...)" + - pattern-not: "xml.dom.expatbuilder.parse(\"...\")" + - pattern: "xml.dom.expatbuilder.parseString(...)" + severity: "WARNING" +- id: python_xml_rule-expatreader + languages: + - "python" + message: | + The application was found using the `xml.sax.expatreader` package for processing XML. Python's + default XML processors suffer from various XML parsing vulnerabilities + and care must be taken when handling XML data. Additionally, depending on the + version of Python, more critical vulnerabilities such as eXternal XML Entity + injection maybe exploitable. + + The `xml.sax` package suffers from the following security risks as of Python 3.7.1: + * Billion laughs / exponential entity expansion - May allow an adversary to cause + a Denial of Service (DoS) against the application parsing arbitrary XML. + * Quadratic blowup entity expansion - Similar to above, but requires a larger input + to cause the Denial of Service. + + To remediate the above issues, consider using the + [defusedxml](https://pypi.org/project/defusedxml/) + library when processing untrusted XML. + + Example parsing an XML document using defusedxml: + ``` + from defusedxml.ElementTree import parse + + # Parse the inventory.xml file + et = parse('inventory.xml') + # Get the root element + root = et.getroot() + # Work with the root element + # ... + ``` + + For more information on the various XML parsers and their vulnerabilities please see: + - https://docs.python.org/3/library/xml.html#xml-vulnerabilities + + For more information on XML security see OWASP's guide: + - https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#python + metadata: + cwe: "CWE-611" + owasp: + - "A4:2017-XML External Entities (XXE)" + - "A03:2021-Injection" + category: "security" + shortDescription: "Improper restriction of XML external entity reference" + security-severity: "Medium" + pattern-either: + - pattern: "xml.dom.expatreader.parse(...)" + - patterns: + - pattern: "xml.dom.expatreader.parseString(...)" + - pattern-not: "xml.dom.expatreader.parseString(\"...\")" + - pattern: "xml.dom.expatreader.parseString(...)" + - pattern: "xml.dom.expatreader.create_parser(...)" + severity: "WARNING" +- id: python_xml_rule-minidom + languages: + - "python" + message: | + The application was found using the `xml.dom.minidom` package for processing XML. Python's + default XML processors suffer from various XML parsing vulnerabilities + and care must be taken when handling XML data. Additionally, depending on the + version of Python, more critical vulnerabilities such as eXternal XML Entity + injection maybe exploitable. + + The `xml.dom.minidom` package suffers from the following security risks as of Python 3.7.1: + * Billion laughs / exponential entity expansion - May allow an adversary to cause + a Denial of Service (DoS) against the application parsing arbitrary XML. + * Quadratic blowup entity expansion - Similar to above, but requires a larger input + to cause the Denial of Service. + + To remediate the above issues, consider using the + [defusedxml](https://pypi.org/project/defusedxml/) + library when processing untrusted XML. + + Example parsing an XML document using defusedxml: + ``` + from defusedxml.ElementTree import parse + + # Parse the inventory.xml file + et = parse('inventory.xml') + # Get the root element + root = et.getroot() + # Work with the root element + # ... + ``` + + For more information on the various XML parsers and their vulnerabilities please see: + - https://docs.python.org/3/library/xml.html#xml-vulnerabilities + + For more information on XML security see OWASP's guide: + - https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#python + metadata: + cwe: "CWE-611" + owasp: + - "A4:2017-XML External Entities (XXE)" + - "A03:2021-Injection" + category: "security" + shortDescription: "Improper restriction of XML external entity reference" + security-severity: "Medium" + pattern-either: + - patterns: + - pattern: "xml.dom.minidom.parseString(...)" + - pattern-not: "xml.dom.minidom.parseString(\"...\")" + - pattern: "xml.dom.minidom.parse(...)" + severity: "WARNING" +- id: python_xml_rule-pulldom + languages: + - "python" + message: | + The application was found using the `xml.dom.pulldom` package for processing XML. Python's + default XML processors suffer from various XML parsing vulnerabilities + and care must be taken when handling XML data. Additionally, depending on the + version of Python, more critical vulnerabilities such as eXternal XML Entity + injection maybe exploitable. + + The `xml.dom.pulldom` package suffers from the following security risks as of Python 3.7.1: + * Billion laughs / exponential entity expansion - May allow an adversary to cause + a Denial of Service (DoS) against the application parsing arbitrary XML. + * Quadratic blowup entity expansion - Similar to above, but requires a larger input + to cause the Denial of Service. + + To remediate the above issues, consider using the + [defusedxml](https://pypi.org/project/defusedxml/) + library when processing untrusted XML. + + Example parsing an XML document using defusedxml: + ``` + from defusedxml.ElementTree import parse + + # Parse the inventory.xml file + et = parse('inventory.xml') + # Get the root element + root = et.getroot() + # Work with the root element + # ... + ``` + + For more information on the various XML parsers and their vulnerabilities please see: + - https://docs.python.org/3/library/xml.html#xml-vulnerabilities + + For more information on XML security see OWASP's guide: + - https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#python + metadata: + cwe: "CWE-611" + owasp: + - "A4:2017-XML External Entities (XXE)" + - "A03:2021-Injection" + category: "security" + shortDescription: "Improper restriction of XML external entity reference" + security-severity: "Medium" + pattern-either: + - patterns: + - pattern: "xml.dom.pulldom.parseString(...)" + - pattern-not: "xml.dom.pulldom.parseString(\"...\")" + - pattern: "xml.dom.pulldom.parse(...)" + severity: "WARNING" +- id: python_xml_rule-sax + languages: + - "python" + message: | + The application was found using the `xml.sax` package for processing XML. + Python's default XML processors suffer from various XML parsing vulnerabilities + and care must be taken when handling XML data. Additionally, depending on the + version of Python, more critical vulnerabilities such as eXternal XML Entity + injection maybe exploitable. + + The `xml.sax` package suffers from the following security risks as of Python 3.7.1: + * Billion laughs / exponential entity expansion - May allow an adversary to cause + a Denial of Service (DoS) against the application parsing arbitrary XML. + * Quadratic blowup entity expansion - Similar to above, but requires a larger input + to cause the Denial of Service. + + To remediate the above issues, consider using the + [defusedxml](https://pypi.org/project/defusedxml/) + library when processing untrusted XML. + + Example parsing an XML document using defusedxml: + ``` + from defusedxml.ElementTree import parse + + # Parse the inventory.xml file + et = parse('inventory.xml') + # Get the root element + root = et.getroot() + # Work with the root element + # ... + ``` + + For more information on the various XML parsers and their vulnerabilities please see: + - https://docs.python.org/3/library/xml.html#xml-vulnerabilities + + For more information on XML security see OWASP's guide: + - https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#python + metadata: + cwe: "CWE-611" + owasp: + - "A4:2017-XML External Entities (XXE)" + - "A03:2021-Injection" + category: "security" + shortDescription: "Improper restriction of XML external entity reference" + security-severity: "Medium" + pattern-either: + - pattern: "xml.sax.parse(...)" + - patterns: + - pattern: "xml.sax.parseString(...)" + - pattern-not: "xml.sax.parseString(\"...\")" + - pattern: "xml.sax.make_parser(...)" + severity: "WARNING" +- id: generic_injection_rule-BiDiTrojanSource + languages: + - "generic" + pattern-regex: '[\x{202A}-\x{202E}\x{2066}-\x{2069}\x{200E}\x{200F}\x{061C}]' + message: | + Unicode bidirectional (BiDi) control characters were detected in source code. + These characters can be used to reorder text and hide malicious code + (CVE-2021-42574). + + BiDi override characters can make code appear different from its actual logic: + - Text that appears as a comment might actually be executable code + - Code that appears harmless might contain hidden malicious logic + - Variable names and string literals may not reflect their true content + + Mitigation Steps: + - Remove any BiDi override characters + - Only use standard ASCII characters in source code + - If BiDi characters are required, thoroughly review the code + + Secure Code Example: + ```java + public class DataProcessor { + // Use standard ASCII characters only + public void processData(String data) { + String cleanInput = data.trim(); // Clean the input + System.out.println("Processing: " + cleanInput); // Clear, readable code + } + } + ``` + + References: + - https://nvd.nist.gov/vuln/detail/CVE-2021-42574 + - https://trojansource.codes/ + metadata: + shortDescription: "Improper control of generation of code ('Code Injection')" + cwe: "CWE-94" + owasp: + - "A03:2021-Injection" + - "A1:2017-Injection" + category: "security" + security-severity: "Low" + severity: "WARNING" + paths: + include: + - "*.py" + - "*.js" + - "*.java" + - "*.c" + - "*.cpp" + - "*.cs" + - "*.go" + - "*.rs" + - "*.php" + - "*.rb" + - "*.scala" + - "*.ts" + - "*.kt" + - "*.m" + - "*.swift" +- id: java_deserialization_rule-InsecureDeserialization + languages: + - java + mode: taint + pattern-sources: + - patterns: + - pattern-inside: | + $FUNC (..., byte[] $X, ...) { + ... + } + - focus-metavariable: $X + pattern-propagators: + - pattern: $V = new ObjectInputStream($X) + from: $X + to: $V + pattern-sinks: + - pattern: $V.readObject(...) + message: | + Deserialization attacks exploit the process of reading serialized data and turning it back into an + object. By constructing malicious objects and serializing them, an adversary may attempt to: + + - Inject code that is executed upon object construction, which occurs during the deserialization process. + - Exploit mass assignment by including fields that are not normally a part of the serialized data but are + read in during deserialization. + + Consider safer alternatives such as serializing data in the JSON format. Ensure any format chosen allows + the application to specify exactly which object types are allowed to be deserialized. Additionally, when + deserializing, never deserialize to base object types like `Object` and only cast to the exact object + type that is expected. + + To protect against mass assignment, only allow deserialization of the specific fields that are required. + If this is not easily done, consider creating an intermediary type that can be serialized with only the + necessary fields exposed. + + For more details on deserialization attacks in general, see OWASP's guide: + https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html + severity: "WARNING" + metadata: + shortDescription: "Deserialization of Untrusted Data" + category: "security" + cwe: "CWE-502" + owasp: + - "A8:2017-Insecure Deserialization" + - "A08:2021-Software and Data Integrity Failures" + technology: + - "java" + security-severity: "Medium" +- id: javascript_crypto_rule-NodeLibcurlSSLVerificationDisable + languages: + - "javascript" + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - pattern-inside: | + $Y = require('node-libcurl') + ... + - pattern-inside: | + import { $Y } from 'node-libcurl' + ... + - pattern-inside: | + import { $K as $Y } from 'node-libcurl' + ... + - pattern: | + $X = new $Y() + pattern-sinks: + - patterns: + - pattern-either: + - pattern: | + $X.setOpt($SSL, 0) + - pattern: | + $X.setOpt($SSL, false) + - metavariable-pattern: + metavariable: $SSL + pattern-either: + - pattern: | + "SSL_VERIFYHOST" + - pattern: | + "SSL_VERIFYPEER" + - pattern: | + $Y.option.SSL_VERIFYHOST + - pattern: | + $Y.option.SSL_VERIFYPEER + message: | + The application was identified disabling the `SSL_VERIFYPEER` and/or the + `SSL_VERIFYHOST` options of the node-libcurl library. These options control + the verification process of SSL/TLS certificates and hostnames. + + - SSL_VERIFYPEER: This option, when enabled, ensures that the SSL certificate + presented by the server is valid and trusted by a Certificate Authority (CA) + that the client also trusts. This is crucial for verifying that the server with + which the client is connecting is authenticated and its certificate is not forged. + - SSL_VERIFYHOST: This option, when enabled, makes sure that the certificate's + common name (CN) or one of its subject alternative names (SANs) matches the + host name in the URL being connected . This is essential for ensuring that + the client is communicating with the correct server and not another server + presenting a valid certificate. + + Disabling these options compromises the security of SSL/TLS connections. It + exposes the application to MITM attacks, where an attacker could intercept, + read, or modify the data sent and received over what is assumed to be a secure + connection. + + Mitigation Strategy: + To mitigate this vulnerability and ensure secure communication, enable SSL/TLS + certificate and hostname verification by setting `SSL_VERIFYPEER` to `1` or + `true` and `SSL_VERIFYHOST` to `2`. These options are enabled by default as + well. This configuration ensures that the server's SSL certificate is validated + against trusted CAs and that the hostname in the certificate matches the hostname + the client intends to communicate with. + + Secure Code Example: + ``` + const { Curl } = require('node-libcurl') + const curl = new Curl() + curl.setOpt('SSL_VERIFYPEER', 1) + curl.setOpt('SSL_VERIFYHOST', 2) + curl.setOpt('URL', 'https://yourserver.com:443') + ``` + severity: "WARNING" + metadata: + owasp: + - "A6:2017-Security Misconfiguration" + - "A05:2021-Security Misconfiguration" + cwe: "CWE-599" + shortDescription: "Missing validation of OpenSSL certificate" + security-severity: "MEDIUM" + category: "security" +- id: python_exec_rule-start-process-partial-path + languages: + - "python" + message: | + Starting a process with a partial executable path + patterns: + - pattern-either: + - patterns: + - pattern: "os.popen(...)" + - pattern-not: "os.popen(\"...\", ...)" + - patterns: + - pattern: "os.system(...)" + - pattern-not: "os.system(\"...\", ...)" + - patterns: + - pattern: "os.popen2(...)" + - pattern-not: "os.popen2(\"...\", ...)" + - patterns: + - pattern: "os.popen3(...)" + - pattern-not: "os.popen3(\"...\", ...)" + - patterns: + - pattern: "os.popen4(...)" + - pattern-not: "os.popen4(\"...\", ...)" + - patterns: + - pattern: "popen2.popen2(...)" + - pattern-not: "popen2.popen2(\"...\", ...)" + - patterns: + - pattern: "popen2.popen3(...)" + - pattern-not: "popen2.popen3(\"...\", ...)" + - patterns: + - pattern: "popen2.popen4(...)" + - pattern-not: "popen2.popen4(\"...\", ...)" + - patterns: + - pattern: "popen2.Popen3(...)" + - pattern-not: "popen2.Popen3(\"...\", ...)" + - patterns: + - pattern: "popen2.Popen4(...)" + - pattern-not: "popen2.Popen4(\"...\", ...)" + - patterns: + - pattern: "commands.getoutput(...)" + - pattern-not: "commands.getoutput(\"...\", ...)" + - patterns: + - pattern: "commands.getstatusoutput(...)" + - pattern-not: "commands.getstatusoutput(\"...\", ...)" + metadata: + cwe: "CWE-78" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + shortDescription: "Improper neutralization of special elements used in an OS Command + ('OS Command Injection')" + security-severity: "High" + category: "security" + severity: "INFO" +- id: python_exec_rule-start-process-path + languages: + - "python" + message: | + Starting a process with a partial executable path + patterns: + - pattern-either: + - pattern: "subprocess.Popen($BIN, shell=False)" + - pattern: "subprocess.Popen([$BIN, ...], shell=False)" + - pattern: "os.system($BIN, shell=False)" + - pattern: "os.system([$BIN, ...], shell=False)" + - pattern: "popen2.Popen3($BIN, shell=False)" + - pattern: "popen2.Popen3([$BIN, ...], shell=False)" + - pattern: "popen2.Popen4($BIN, shell=False)" + - pattern: "popen2.Popen4([$BIN, ...], shell=False)" + - pattern: "commands.getoutput($BIN, shell=False)" + - pattern: "commands.getoutput([$BIN, ...], shell=False)" + - pattern: "commands.getstatusoutput($BIN, shell=False)" + - pattern: "commands.getstatusoutput([$BIN, ...], shell=False)" + - metavariable-regex: + metavariable: "$BIN" + regex: "^['\"][^/\\.][^:].*['\"]" + metadata: + cwe: "CWE-78" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + shortDescription: "Improper neutralization of special elements used in an OS Command + ('OS Command Injection')" + security-severity: "High" + category: "security" + severity: "ERROR" +- id: python_exec_rule-subprocess-call-array + languages: + - "python" + message: | + subprocess call - check for execution of untrusted input + patterns: + - pattern: | + subprocess.$FUNC([..., $ARG, ...]) + - metavariable-pattern: + metavariable: "$ARG" + patterns: + - pattern-not: | + "..." + - pattern-not: | + '...' + metadata: + cwe: "CWE-78" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + shortDescription: "Improper neutralization of special elements used in an OS Command + ('OS Command Injection')" + security-severity: "High" + category: "security" + severity: "WARNING" +- id: scala_unsafe_rule-InformationExposureVariant2 + languages: + - "scala" + message: | + The sensitive information may be valuable information on its own (such as a password), or it + may be useful for launching other, more deadly attacks. If an attack fails, an attacker may use + error information provided by the server to launch another more focused attack. For example, an + attempt to exploit a path traversal weakness (CWE-22) might yield the full pathname of the + installed application. + metadata: + category: "security" + cwe: "CWE-209" + shortDescription: "Information Exposure Through an Error Message" + technology: + - "scala" + security-severity: "Info" + patterns: + - pattern-either: + - pattern: "$E.printStackTrace" + - patterns: + - pattern: "$E.printStackTrace($OUT)" + - metavariable-pattern: + metavariable: "$OUT" + pattern-either: + - pattern: "($PS: java.io.PrintStream)" + - pattern: "($PW: java.io.PrintWriter)" + - pattern: "java.lang.System.out" + - pattern: "($O: java.io.OutputStream)" + - pattern: "($SOS: javax.servlet.ServletOutputStream)" + severity: "WARNING" +- id: java_cookie_rule-CookieHTTPOnly + languages: + - "java" + patterns: + - pattern-either: + - pattern: ($X.servlet.http.Cookie $COOKIE).setHttpOnly(false); + - patterns: + - pattern-not-inside: ($X.servlet.http.Cookie $COOKIE).setHttpOnly(...); ... + - pattern: $RESPONSE.addCookie($COOKIE); + message: | + The `HttpOnly` attribute when set to `true` protects the cookie value from being accessed by + client side JavaScript such + as reading the `document.cookie` values. By enabling this protection, a website that is + vulnerable to + Cross-Site Scripting (XSS) will be able to block malicious scripts from accessing the cookie + value from JavaScript. + + Example of protecting a `Cookie`: + ``` + // Create an HttpOnly cookie. + Cookie someCookie = new Cookie("SomeCookieName", "SomeValue"); + // Set HttpOnly flag to true + someCookie.setHttpOnly(true); + ``` + + For more information see: + https://jakarta.ee/specifications/servlet/4.0/apidocs/javax/servlet/http/cookie#setHttpOnly-boolean- + + Session cookies should be configured with the following security directives: + + - [HTTPOnly](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#restrict_access_to_cookies) + - [Secure](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#restrict_access_to_cookies) + - [SameSite](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite) + severity: "WARNING" + metadata: + shortDescription: "Sensitive cookie without 'HttpOnly' flag" + category: "security" + owasp: + - "A6:2017-Security Misconfiguration" + - "A05:2021-Security Misconfiguration" + cwe: "CWE-1004" + technology: + - "java" + security-severity: "Low" +- id: java_crypto_rule-DisallowOldTLSVersion + languages: + - "java" + patterns: + - pattern: $VALUE. ... .setProperty("jdk.tls.client.protocols", "$PATTERNS"); + - metavariable-pattern: + metavariable: $PATTERNS + language: generic + patterns: + - pattern-either: + - pattern-regex: ^(.*TLSv1|.*SSLv.*)$ + - pattern-regex: ^(.*TLSv1,.*|.*TLSv1.1.*) + message: | + This application sets the `jdk.tls.client.protocols` system property to + include insecure TLS or SSL versions (SSLv3, TLSv1, TLSv1.1), which are + deprecated due to serious security vulnerabilities like POODLE attacks and + susceptibility to man-in-the-middle attacks. Continuing to use these + protocols can expose data to interception or manipulation. + + To mitigate the issue, upgrade to TLSv1.2 or higher, which provide stronger + encryption and improved security. Refrain from using any SSL versions as they + are entirely deprecated. + + Secure Code Example: + ``` + public void safe() { + java.lang.System.setProperty("jdk.tls.client.protocols", "TLSv1.3"); + } + ``` + severity: "WARNING" + metadata: + likelihood: "MEDIUM" + impact: "MEDIUM" + confidence: "MEDIUM" + shortDescription: "Inadequate encryption strength" + category: "security" + cwe: "CWE-326" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + security-severity: "MEDIUM" + references: + - "https://stackoverflow.com/questions/26504653/is-it-possible-to-disable-sslv3-for-all-java-applications" + subcategory: + - "vuln" + technology: + - "java" + vulnerability: "Insecure Transport" + license: "Commons Clause License Condition v1.0[LGPL-2.1-only]" + vulnerability_class: + - "Mishandled Sensitive Information" +- id: java_crypto_rule-GCMNonceReuse + metadata: + shortDescription: "Reuse of cryptographic initialization vector" + category: "security" + cwe: "CWE-323" + technology: + - "java" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + security-severity: "MEDIUM" + languages: + - java + message: | + GCM is a mode of operation for symmetric-key cryptographic block ciphers. GCM allows the usage of + an initialization vector or nonce used to provide the initial state. The IV is an arbitrary number + that can be used just once in a cryptographic communication. Re use of initialization vectors + nullifies their usage, as the initial state of all GCMs with the same vector will effectively be + the same. + + Instead of hard coding an initialization vector, it is recommended to use nextBytes() method from + java.security.SecureRandom. This generates a user specified number of random bytes. + + Example using `java.security.SecureRandom`: + ``` + Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); + SecretKeySpec keySpec = new SecretKeySpec(secretKey.getEncoded(), "AES"); + + // Generate a new, random IV for each encryption operation + SecureRandom secureRandom = new SecureRandom(); + // GCM standard recommends a 12-byte (96-bit) IV + byte[] iv = new byte[12]; + secureRandom.nextBytes(iv); + + GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(GCM_TAG_LENGTH * 8, iv); + cipher.init(Cipher.ENCRYPT_MODE, keySpec, gcmParameterSpec); + ``` + + For more information on Java Cryptography see: + https://docs.oracle.com/en/java/javase/15/security/java-cryptography-architecture-jca-reference-guide.html + mode: taint + pattern-sources: + - pattern-either: + - pattern: new byte[]{...}; + - pattern: $STRING.getBytes(); + pattern-sinks: + - pattern: new GCMParameterSpec(...,$NONCE, ...) + severity: "WARNING" +- id: java_crypto_rule-HTTPUrlConnectionHTTPRequest + message: | + Detected an HTTP request sent via HttpURLConnection or URLConnection. + This could lead to sensitive information being sent over an insecure + channel, as HTTP does not encrypt data. Transmitting data over HTTP + exposes it to potential interception by attackers, risking data + integrity and confidentiality. Using HTTP for transmitting sensitive + data such as passwords, personal information, or financial details can + lead to information disclosure. + + To mitigate the issue, switch to HTTPS to ensure all data transmitted + is securely encrypted. This helps protect against eavesdropping and + man-in-the-middle attacks. Modify the URL in your code from HTTP to + HTTPS and ensure the server supports HTTPS. + + Secure Code Example: + ``` + private static void safe() { + try { + URL url = new URL("https://example.com/api/data"); // Changed to HTTPS + HttpURLConnection con = (HttpURLConnection) url.openConnection(); + con.setRequestMethod("GET"); + + int status = con.getResponseCode(); + if (status == HttpURLConnection.HTTP_OK) { + BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream())); + String inputLine; + StringBuilder response = new StringBuilder(); + while ((inputLine = in.readLine()) != null) { + response.append(inputLine); + } + in.close(); + System.out.println("Response: " + response.toString()); + } else { + System.out.println("HTTP error code: " + status); + } + con.disconnect(); + } catch (Exception e) { + e.printStackTrace(); + } + } + ``` + severity: "WARNING" + metadata: + likelihood: "MEDIUM" + impact: "MEDIUM" + confidence: "MEDIUM" + shortDescription: "Cleartext transmission of sensitive information" + category: "security" + cwe: "CWE-319" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + security-severity: "MEDIUM" + references: + - "https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/net/URLConnection.html" + - "https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/net/URL.html#openConnection()" + subcategory: + - "vuln" + technology: + - "java" + vulnerability: "Insecure Transport" + license: "Commons Clause License Condition v1.0[LGPL-2.1-only]" + vulnerability_class: + - "Mishandled Sensitive Information" + languages: + - "java" + patterns: + - pattern: | + "=~/[Hh][Tt][Tt][Pp]://.*/" + - pattern-either: + - pattern-inside: | + URL $URL = new URL ("=~/[Hh][Tt][Tt][Pp]://.*/", ...); + ... + $CON = (HttpURLConnection) $URL.openConnection(...); + ... + $CON.$FUNC(...); + - pattern-inside: | + URL $URL = new URL ("=~/[Hh][Tt][Tt][Pp]://.*/", ...); + ... + $CON = $URL.openConnection(...); + ... + $CON.$FUNC(...); +- id: java_crypto_rule-HttpComponentsRequest + message: | + Detected an HTTP GET request sent via Apache HTTP Components. Sending data + over HTTP can expose sensitive information to interception or modification + by attackers, as HTTP does not encrypt the data transmitted. It is critical + to use HTTPS, which encrypts the communication, to protect the confidentiality + and integrity of data in transit. + + To mitigate the issue, ensure all data transmitted between the client and + server is sent over HTTPS. Update all HTTP URLs to HTTPS and configure your + server to redirect HTTP requests to HTTPS. Additionally, implement HSTS + (HTTP Strict Transport Security) to enforce secure connections. + Secure Code Example: + ``` + private static void safe() { + CloseableHttpClient httpclient = HttpClients.createDefault(); + CloseableHttpResponse response = httpclient.execute(new HttpPost("https://example.com")); + } + ``` + severity: WARNING + metadata: + shortDescription: "Cleartext transmission of sensitive information" + security-severity: "MEDIUM" + likelihood: "MEDIUM" + impact: "MEDIUM" + confidence: "MEDIUM" + category: "security" + cwe: "CWE-319" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + references: + - "https://hc.apache.org/httpcomponents-client-ga/quickstart.html" + subcategory: + - "vuln" + technology: + - "java" + vulnerability: "Insecure Transport" + license: "Commons Clause License Condition v1.0[LGPL-2.1-only]" + vulnerability_class: + - "Mishandled Sensitive Information" + languages: + - "java" + mode: taint + pattern-sources: + - pattern: | + "=~/^http://.+/i" + pattern-sinks: + - pattern: (org.apache.http.impl.client.CloseableHttpClient $A).execute($HTTPREQ); +- id: java_crypto_rule-HttpGetHTTPRequest + languages: + - "java" + mode: taint + pattern-sources: + - pattern: | + "=~/^http:\/\/.+/i" + pattern-sinks: + - patterns: + - pattern: | + $R = new org.apache.http.client.methods.HttpGet($PROT); + ... + $CLIENT. ... .execute($R, ...); + - focus-metavariable: $PROT + message: | + Detected an HTTP GET request sent via HttpGet. Sending data over HTTP can + expose sensitive information to interception or modification by attackers, + as HTTP does not encrypt the data transmitted. It is critical to use + HTTPS, which encrypts the communication, to protect the confidentiality + and integrity of data in transit. + + To mitigate the issue, ensure all data transmitted between the client and + server is sent over HTTPS. Update all HTTP URLs to HTTPS and configure your + server to redirect HTTP requests to HTTPS. Additionally, implement HSTS + (HTTP Strict Transport Security) to enforce secure connections. + + Secure Code Example: + ``` + private static void safe() throws IOException { + HttpGet httpGet = new HttpGet("https://example.com"); + HttpClients.createDefault().execute(httpGet); + } + ``` + severity: "WARNING" + metadata: + likelihood: "MEDIUM" + impact: "MEDIUM" + confidence: "MEDIUM" + cwe: "CWE-319" + category: "security" + shortDescription: "Cleartext transmission of sensitive information" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + security-severity: "MEDIUM" + references: + - "https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/net/URLConnection.html" + - "https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/net/URL.html#openConnection()" + subcategory: + - "vuln" + technology: + - "java" + vulnerability: "Insecure Transport" + license: "Commons Clause License Condition v1.0[LGPL-2.1-only]" + vulnerability_class: + - "Mishandled Sensitive Information" +- id: java_crypto_rule_JwtDecodeWithoutVerify + languages: + - "java" + message: Detected the decoding of a JWT token without a verify step. JWT tokens + must be verified before use, otherwise the token's integrity is unknown. + This means a malicious actor could forge a JWT token with any claims. Call + '.verify()' before using the token. + metadata: + shortDescription: "Improper verification of cryptographic signature" + category: "security" + cwe: "CWE-347" + owasp: + - "A8:2017-Insecure Deserialization" + - "A08:2021-Software and Data Integrity Failures" + source-rule-url: https://semgrep.dev/blog/2020/hardcoded-secrets-unverified-tokens-and-other-common-jwt-mistakes/ + technology: jwt + confidence: MEDIUM + references: https://owasp.org/Top10/A08_2021-Software_and_Data_Integrity_Failures + subcategory: vuln + likelihood: LOW + impact: HIGH + license: Commons Clause License Condition v1.0[LGPL-2.1-only] + vulnerability_class: Improper Authentication + security-severity: "MEDIUM" + severity: WARNING + patterns: + - pattern: | + com.auth0.jwt.JWT.decode(...); + - pattern-not-inside: |- + class $CLASS { + ... + $RETURNTYPE $FUNC (...) { + ... + $VERIFIER.verify(...); + ... + } + } +- id: java_crypto_rule_JwtNoneAlgorithm + message: | + Detected use of the 'none' algorithm in a JWT token. The 'none' + algorithm assumes the integrity of the token has already been verified. + This would allow a malicious actor to forge a JWT token that will + automatically be verified. Do not explicitly use the 'none' algorithm. + Instead, use an algorithm such as 'HS256'. + + For more information on how to securely use JWT please see OWASP: + - https://cheatsheetseries.owasp.org/cheatsheets/JSON_Web_Token_for_Java_Cheat_Sheet.html + metadata: + shortDescription: "Use of a broken or risky cryptographic algorithm" + cwe: "CWE-327" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + source-rule-url: https://semgrep.dev/blog/2020/hardcoded-secrets-unverified-tokens-and-other-common-jwt-mistakes/ + asvs: + section: "V3: Session Management Verification Requirements" + control_id: 3.5.3 Insecue Stateless Session Tokens + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x12-V3-Session-management.md#v35-token-based-session-management + version: "4" + category: security + technology: + - jwt + confidence: LOW + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + license: Commons Clause License Condition v1.0[LGPL-2.1-only] + vulnerability_class: + - Cryptographic Issues + security-severity: "CRITICAL" + languages: + - java + severity: ERROR + pattern-either: + - patterns: + - pattern: | + io.jsonwebtoken.Jwts.builder() + - pattern-not-inside: | + $RETURNTYPE $FUNC(...) { + ... + $JWTS.signWith(...); + ... + } + - pattern: | + $J.sign(com.auth0.jwt.algorithms.Algorithm.none()) + - pattern: | + new com.nimbusds.jose.PlainHeader(...); + - pattern: | + new com.nimbusds.jose.PlainHeader.Builder(). ... .build(); +- id: java_crypto_rule-SocketRequestUnsafeProtocols + message: | + This code establishes a network connection using an insecure protocol + (HTTP, FTP, or Telnet). These protocols transmit data in cleartext, which + can be intercepted and read by malicious actors. This exposure of + sensitive information violates security best practices and can lead to + data breaches. + + To mitigate the vulnerability, consider using secure protocols that encrypt + the transmission of data. For web traffic, replace HTTP with HTTPS, which + uses SSL/TLS to protect the data in transit. For file transfers, use SFTP + or FTPS instead of FTP. For remote terminal access, use SSH instead of Telnet. + + Secure Code Example: + ``` + public void safe() { + BufferedReader in = null; + PrintWriter out = null; + Socket pingSocket = null; + try{ + pingSocket = new Socket("ssh://example.com", 22); + out = new PrintWriter(pingSocket.getOutputStream(), true); + in = new BufferedReader(new InputStreamReader(pingSocket.getInputStream())); + out.println("ping"); + System.out.println(in.readLine()); + } catch (Exception e) { + e.printStackTrace(); + } finally { + try { + if (in != null) in.close(); + if (pingSocket != null) pingSocket.close(); + } catch (IOException e) { + System.out.println("Failed to close resources: " + e.getMessage()); + } + } + } + ``` + severity: "WARNING" + metadata: + likelihood: "MEDIUM" + impact: "MEDIUM" + confidence: "LOW" + category: "security" + cwe: "CWE-319" + shortDescription: "Cleartext transmission of sensitive information" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + security-severity: "MEDIUM" + references: + - "https://docs.oracle.com/javase/8/docs/api/java/net/Socket.html" + technology: + - "java" + vulnerability: "Insecure Transport" + license: "Commons Clause License Condition v1.0[LGPL-2.1-only]" + vulnerability_class: + - "Mishandled Sensitive Information" + languages: + - "java" + pattern-either: + - pattern: | + $SOCKET = new java.net.Socket("=~/^ftp://.+/i", ...); + - pattern: | + $SOCKET = new java.net.Socket("=~/^http://.+/i", ...); + - pattern: | + $SOCKET = new java.net.Socket("=~/^telnet://.+/i", ...); + - patterns: + - pattern: | + $SOCKET = new java.net.Socket("...", $PORT); + - metavariable-comparison: + comparison: $PORT in [23,21,80] + metavariable: $PORT +- id: java_crypto_rule-SpringFTPRequest + languages: + - "java" + mode: taint + pattern-sources: + - pattern: | + "=~/^ftp://.+/i" + pattern-sinks: + - patterns: + - pattern: | + (org.springframework.integration.ftp.session.DefaultFtpSessionFactory + $SF).setHost($URL); + - focus-metavariable: $URL + message: | + This pattern detects configurations where the Spring Integration FTP plugin + is used to set up connections to FTP servers. FTP is an insecure protocol + that transmits data, including potentially sensitive information, in plaintext. + This can expose personal identifiable information (PII) or other sensitive data + to interception by attackers during transmission. + + To mitigate the vulnerability, switch to a secure protocol such as SFTP or FTPS + that encrypts the connection to prevent data exposure. Ensure that any method + used to set the host for an FTP session does not use plaintext FTP. + + Secure Code Example: + ``` + public SessionFactory safe(FtpSessionFactoryProperties properties) { + DefaultFtpSessionFactory ftpSessionFactory = new DefaultFtpSessionFactory(); + ftpSessionFactory.setHost("sftp://example.com"); + ftpSessionFactory.setPort(properties.getPort()); + ftpSessionFactory.setUsername(properties.getUsername()); + ftpSessionFactory.setPassword(properties.getPassword()); + ftpSessionFactory.setClientMode(properties.getClientMode().getMode()); + return ftpSessionFactory; + } + ``` + severity: "WARNING" + metadata: + likelihood: "MEDIUM" + impact: "MEDIUM" + confidence: "MEDIUM" + cwe: "CWE-319" + category: "security" + shortDescription: "Cleartext transmission of sensitive information" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + security-severity: "MEDIUM" + references: + - "https://docs.spring.io/spring-integration/api/org/springframework/integration/ftp/session/AbstractFtpSessionFactory.html#setClientMode-int-" + subcategory: + - "vuln" + technology: + - "spring" + vulnerability: "Insecure Transport" + license: "Commons Clause License Condition v1.0[LGPL-2.1-only]" + vulnerability_class: + - "Mishandled Sensitive Information" + +- id: java_crypto_rule-SpringHTTPRequestRestTemplate + message: | + This rule detects instances where Java Spring's RestTemplate API sends + requests to non-secure (http://) URLs. Sending data over HTTP is vulnerable + as it does not use TLS encryption, exposing the data to interception, + modification, or redirection by attackers. + + To mitigate this vulnerability, modify the request URLs to use HTTPS instead, + which ensures that the data is encrypted during transit and prevents from + MITM attacks. + + Secure Code Example: + ``` + public void safe(Object obj) throws Exception { + RestTemplate restTemplate = new RestTemplate(); + restTemplate.put(URI.create("https://example.com"), obj); + } + ``` + severity: "WARNING" + metadata: + likelihood: "MEDIUM" + impact: "MEDIUM" + confidence: "MEDIUM" + category: "security" + cwe: "CWE-319" + shortDescription: "Cleartext transmission of sensitive information" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + security-severity: "MEDIUM" + references: + - "https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/client/RestTemplate.html#delete-java.lang.String-java.util.Map-" + - "https://www.baeldung.com/rest-template" + subcategory: + - "vuln" + technology: + - "spring" + vulnerability: "Insecure Transport" + license: "Commons Clause License Condition v1.0[LGPL-2.1-only]" + vulnerability_class: + - "Mishandled Sensitive Information" + languages: + - "java" + mode: "taint" + pattern-sources: + - pattern: | + "=~/^http:\/\/.+/i" + pattern-sinks: + - patterns: + - pattern: | + (org.springframework.web.client.RestTemplate $RESTTEMP).$FUNC($URL, ...); + - focus-metavariable: $URL + - metavariable-regex: + metavariable: $FUNC + regex: (delete|doExecute|exchange|getForEntity|getForObject|headForHeaders|optionsForAllow|patchForObject|postForEntity|postForLocation|postForObject|put|execute) + +- id: java_crypto_rule-TLSUnsafeRenegotiation + languages: + - "java" + patterns: + - pattern: | + java.lang.System.setProperty("sun.security.ssl.allowUnsafeRenegotiation", $TRUE); + - metavariable-pattern: + metavariable: $TRUE + pattern-either: + - pattern: | + true + - pattern: | + "true" + - pattern: | + Boolean.TRUE + message: | + This code enables unsafe renegotiation in SSL/TLS connections, which is + vulnerable to man-in-the-middle attacks. In such attacks, an attacker + could inject chosen plaintext at the beginning of the secure + communication, potentially compromising the security of data transmission. If + exploited, this vulnerability can lead to unauthorized access to sensitive + data, data manipulation, and potentially full system compromise depending on + the data and operations protected by the TLS session. + + To mitigate this vulnerability, disable unsafe renegotiation in the Java + application. Ensure that only secure renegotiation is allowed by setting the + system property `sun.security.ssl.allowUnsafeRenegotiation` to `false`. + + Secure code example: + ``` + public void safe() { + java.lang.System.setProperty("sun.security.ssl.allowUnsafeRenegotiation", false); + } + ``` + severity: "WARNING" + metadata: + likelihood: "LOW" + impact: "MEDIUM" + confidence: "MEDIUM" + category: "security" + cwe: "CWE-319" + shortDescription: "Cleartext transmission of sensitive information" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + security-severity: "MEDIUM" + references: + - "https://www.oracle.com/java/technologies/javase/tlsreadme.html" + subcategory: + - "vuln" + technology: + - "java" + vulnerability: "Insecure Transport" + license: "Commons Clause License Condition v1.0[LGPL-2.1-only]" + vulnerability_class: + - "Mishandled Sensitive Information" +- id: java_crypto_rule-TelnetRequest + message: | + Checks for attempts to connect through telnet. Telnet is an outdated + protocol that transmits all data, including sensitive information like + passwords, in clear text. This exposes it to interception and + eavesdropping on unsecured networks. + + To mitigate this issue, replace Telnet usage with more secure protocols + such as SSH (Secure Shell), which provides encrypted communication. Use + the SSH functionality provided by libraries like JSch or Apache MINA SSHD + for secure data transmission. + + Secure Code Example: + ``` + import com.jcraft.jsch.JSch; + import com.jcraft.jsch.Session; + + public class SecureConnector { + public static void main(String[] args) { + try { + JSch jsch = new JSch(); + Session session = jsch.getSession("username", "hostname", 22); + session.setPassword("password"); + session.setConfig("StrictHostKeyChecking", "no"); + session.connect(); + System.out.println("Connected securely."); + } catch (Exception e) { + System.err.println("Secure connection failed: " + e.getMessage()); + } + } + } + ``` + severity: "WARNING" + metadata: + likelihood: "MEDIUM" + impact: "MEDIUM" + confidence: "MEDIUM" + category: "security" + cwe: "CWE-319" + shortDescription: "Cleartext transmission of sensitive information" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + security-severity: "MEDIUM" + references: + - "https://commons.apache.org/proper/commons-net/javadocs/api-3.6/org/apache/commons/net/telnet/TelnetClient.html" + subcategory: + - "vuln" + technology: + - "java" + vulnerability: "Insecure Transport" + license: "Commons Clause License Condition v1.0[LGPL-2.1-only]" + vulnerability_class: + - "Mishandled Sensitive Information" + languages: + - "java" + pattern: | + (org.apache.commons.net.telnet.TelnetClient $TELNETCLIENT).connect(...); +- id: java_crypto_rule-UnirestHTTPRequest + languages: + - "java" + patterns: + - pattern: | + Unirest.$METHOD("=~/[hH][tT][tT][pP]://.*/") + message: | + This application uses the Unirest library to send + network requests to URLs starting with 'http://'. Communicating over HTTP + is considered insecure because it does not encrypt traffic with TLS + (Transport Layer Security), exposing data to potential interception or + manipulation by attackers. + + To mitigate the issue, modify the request URL to begin with 'https://' + instead of 'http://'. Using HTTPS ensures that the data is encrypted and + secure during transmission. Review all instances where HTTP is used and + update them to use HTTPS to prevent security risks. + + Secure Code Example: + ``` + import kong.unirest.core.Unirest; + + public void safe() { + Unirest.get("https://httpbin.org") + .queryString("fruit", "apple") + .queryString("droid", "R2D2") + .asString(); + } + ``` + severity: "WARNING" + metadata: + likelihood: "MEDIUM" + impact: "MEDIUM" + confidence: "MEDIUM" + category: "security" + cwe: "CWE-319" + shortDescription: "Cleartext transmission of sensitive information" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + security-severity: "MEDIUM" + references: + - "https://kong.github.io/unirest-java/#requests" + subcategory: + - "vuln" + technology: + - "unirest" + vulnerability: "Insecure Transport" + license: "Commons Clause License Condition v1.0[LGPL-2.1-only]" + vulnerability_class: + - "Mishandled Sensitive Information" +- id: java_crypto_rule-UseOfRC2 + languages: + - java + pattern-either: + - pattern: | + javax.crypto.Cipher.getInstance("RC2") + - patterns: + - pattern-inside: | + class $CLS{ + ... + String $ALG = "RC2"; + ... + } + - pattern: | + javax.crypto.Cipher.getInstance($ALG); + message: | + Use of RC2, a deprecated cryptographic algorithm vulnerable to related-key + attacks, was detected. Modern cryptographic standards recommend the + adoption of algorithms that integrate message integrity to ensure the + ciphertext remains unaltered. + + To mitigate the issue, use any of the below algorithms instead: + 1. `ChaCha20Poly1305` - Preferred for its simplicity and speed, suitable for + environments where cryptographic acceleration is absent. + 2. `AES-256-GCM` - Highly recommended when hardware support is available, + despite being somewhat slower than `ChaCha20Poly1305`. It is crucial to avoid + nonce reuse with AES-256-GCM to prevent security compromises. + + Secure code example using `ChaCha20Poly1305` in Java: + ``` + public void encryptAndDecrypt() throws Exception { + SecureRandom random = new SecureRandom(); + byte[] secretKey = new byte[32]; // 256-bit key + byte[] nonce = new byte[12]; // 96-bit nonce + random.nextBytes(secretKey); + random.nextBytes(nonce); + + Cipher cipher = Cipher.getInstance("ChaCha20-Poly1305/None/NoPadding"); + SecretKeySpec keySpec = new SecretKeySpec(secretKey, "ChaCha20"); + GCMParameterSpec spec = new GCMParameterSpec(128, nonce); + + cipher.init(Cipher.ENCRYPT_MODE, keySpec, spec); + byte[] plaintext = "Secret text".getBytes(StandardCharsets.UTF_8); + byte[] ciphertext = cipher.doFinal(plaintext); + System.out.println("Encrypted: " + Base64.getEncoder().encodeToString(ciphertext)); + + cipher.init(Cipher.DECRYPT_MODE, keySpec, spec); + byte[] decrypted = cipher.doFinal(ciphertext); + System.out.println("Decrypted: " + new String(decrypted, StandardCharsets.UTF_8)); + } + ``` + For more on Java Cryptography, refer: + https://docs.oracle.com/en/java/javase/15/security/java-cryptography-architecture-jca-reference-guide.html + severity: "WARNING" + metadata: + shortDescription: "Use of a broken or risky cryptographic algorithm" + category: "security" + cwe: "CWE-327" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + technology: + - "java" + security-severity: "MEDIUM" + references: + - "https://owasp.org/Top10/A02_2021-Cryptographic_Failures" + subcategory: + - "vuln" + likelihood: "MEDIUM" + impact: "MEDIUM" + confidence: "HIGH" +- id: java_crypto_rule-UseOfRC4 + languages: + - java + pattern-either: + - pattern: | + javax.crypto.Cipher.getInstance("RC4") + - patterns: + - pattern-inside: | + class $CLS{ + ... + String $ALG = "RC4"; + ... + } + - pattern: | + javax.crypto.Cipher.getInstance($ALG); + message: | + Use of RC4 was detected. RC4 is vulnerable to several types of attacks, + including stream cipher attacks where attackers can recover plaintexts by + analyzing a large number of encrypted messages, and bit-flipping attacks + that can alter messages without knowing the encryption key. + + To mitigate the issue, use any of the below algorithms instead: + 1. `ChaCha20Poly1305` - Preferred for its simplicity and speed, suitable for + environments where cryptographic acceleration is absent. + 2. `AES-256-GCM` - Highly recommended when hardware support is available, + despite being somewhat slower than `ChaCha20Poly1305`. It is crucial to avoid + nonce reuse with AES-256-GCM to prevent security compromises. + + Secure code example using `ChaCha20Poly1305` in Java: + ``` + public void encryptAndDecrypt() throws Exception { + SecureRandom random = new SecureRandom(); + byte[] secretKey = new byte[32]; // 256-bit key + byte[] nonce = new byte[12]; // 96-bit nonce + random.nextBytes(secretKey); + random.nextBytes(nonce); + + Cipher cipher = Cipher.getInstance("ChaCha20-Poly1305/None/NoPadding"); + SecretKeySpec keySpec = new SecretKeySpec(secretKey, "ChaCha20"); + GCMParameterSpec spec = new GCMParameterSpec(128, nonce); + + cipher.init(Cipher.ENCRYPT_MODE, keySpec, spec); + byte[] plaintext = "Secret text".getBytes(StandardCharsets.UTF_8); + byte[] ciphertext = cipher.doFinal(plaintext); + System.out.println("Encrypted: " + Base64.getEncoder().encodeToString(ciphertext)); + + cipher.init(Cipher.DECRYPT_MODE, keySpec, spec); + byte[] decrypted = cipher.doFinal(ciphertext); + System.out.println("Decrypted: " + new String(decrypted, StandardCharsets.UTF_8)); + } + ``` + For more information, refer: + https://owasp.org/www-community/Using_the_Java_Cryptographic_Extensions + severity: "WARNING" + metadata: + shortDescription: "Use of a broken or risky cryptographic algorithm" + category: "security" + cwe: "CWE-327" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + technology: + - "java" + security-severity: "MEDIUM" + references: + - "https://owasp.org/Top10/A02_2021-Cryptographic_Failures" + - "https://googleprojectzero.blogspot.com/2022/10/rc4-is-still-considered-harmful.html" + subcategory: + - "vuln" + likelihood: "MEDIUM" + impact: "MEDIUM" + confidence: "HIGH" +- id: java_csrf_rule-SpringCSRFDisabled + languages: + - "java" + pattern-either: + - pattern: (org.springframework.security.config.annotation.web.builders.HttpSecurity $H). ... .csrf(...). ... .requireCsrfProtectionMatcher(...) + - pattern: (org.springframework.security.config.annotation.web.builders.HttpSecurity $H). ... .csrf(...). ... .disable(...) + - pattern: (org.springframework.security.config.annotation.web.configurers.CsrfConfigurer $C). ... .disable(); + message: | + The application fails to protect against Cross-Site Request Forgery (CSRF) + due to disabling Spring's CSRF protection features. + + This vulnerability may allow attackers to carry out CSRF attacks by crafting + malicious links or forms on external websites. Victims who are tricked into + accessing these links while authenticated in your application could inadvertently + perform actions that the attacker intends, such as changing user information, + initiating transactions, or altering permissions. + + To remediate this issue, remove the call to `HttpSecurity.csrf().disable()` or + remove the custom `CsrfConfigurer`. + + For more information on CSRF protection in Spring see: + https://docs.spring.io/spring-security/reference/servlet/exploits/csrf.html#servlet-csrf + + Additionally, consider setting all session cookies to have the `SameSite=Strict` + attribute. It should be noted that this may impact usability when sharing links + across other mediums. + It is recommended that a two cookie based approach is taken, as outlined in the + [Top level + navigations](https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis-08#section-8.8.2) + section of the SameSite RFC. + + For more information on CSRF see OWASP's guide: + https://owasp.org/www-community/attacks/csrf + metadata: + shortDescription: "Cross-Site Request Forgery (CSRF)" + category: "security" + cwe: "CWE-352" + owasp: + - "A5:2017-Broken Access Control" + - "A01:2021-Broken Access Control" + security-severity: "Medium" + severity: "WARNING" +- id: java_csrf_rule-UnrestrictedRequestMapping + languages: + - "java" + patterns: + - pattern-inside: | + @RequestMapping(...) + $RETURNTYPE $METHOD(...) { ... } + - pattern-not-inside: | + @RequestMapping(..., method = $X, ...) + $RETURNTYPE $METHOD(...) { ... } + - pattern: | + RequestMapping + message: | + Detected a method annotated with 'RequestMapping' that does not specify + the HTTP method. CSRF protections are not enabled for GET, HEAD, TRACE, or + OPTIONS, and by default all HTTP methods are allowed when the HTTP method + is not explicitly specified. This means that a method that performs state + changes could be vulnerable to CSRF attacks. Cross-Site Request Forgery (CSRF) + is a security vulnerability where an attacker tricks a user into performing + unintended actions on a web application where they are authenticated. This + can lead to unauthorized actions like changing user settings, transferring + funds, or altering passwords, all without the user's knowledge, by exploiting + the trust a web application has in the user's browser. + + To mitigate, add the 'method' field and specify the HTTP method (such as + 'RequestMethod.POST'). + + Secure Code Example: + ``` + @RequestMapping(value = "/path", method = RequestMethod.POST) + public void safe() { + // State-changing operations performed within this method. + } + ``` + severity: "WARNING" + metadata: + shortDescription: "Cross-site request forgery (CSRF)" + category: "security" + cwe: "CWE-352" + owasp: + - "A5:2017-Broken Access Control" + - "A01:2021-Broken Access Control" + security-severity: "MEDIUM" + source-rule-url: "https://find-sec-bugs.github.io/bugs.htm#SPRING_CSRF_UNRESTRICTED_REQUEST_MAPPING" + references: + - "https://find-sec-bugs.github.io/bugs.htm#SPRING_CSRF_UNRESTRICTED_REQUEST_MAPPING" + technology: + - "spring" + cwe2022-top25: "true" + cwe2021-top25: "true" + subcategory: + - "audit" + likelihood: "LOW" + impact: "MEDIUM" + confidence: "LOW" + license: "Commons Clause License Condition v1.0[LGPL-2.1-only]" + vulnerability_class: + - "Cross-Site Request Forgery (CSRF)" + +- id: java_deserialization_rule-InsecureJmsDeserialization + languages: + - java + patterns: + - pattern-inside: | + class $JMS_LISTENER implements MessageListener { + ... + public void onMessage(Message $JMS_MSG) { + ... + } + } + - pattern: $Y.getObject(...); + message: | + Deserialization of untrusted JMS ObjectMessage can lead to arbitrary + code execution. This vulnerability occurs when `ObjectMessage.getObject()` + is called to deserialize the payload of an ObjectMessage, potentially + allowing remote attackers to execute arbitrary code with the permissions + of the JMS MessageListener application. + + To mitigate the issue, avoid deserialization of untrusted data and + consider alternative message formats or explicit whitelisting of + allowable classes for deserialization. + + To implement allowlisting, override the ObjectInputStream#resolveClass() + method to limit deserialization to allowed classes only. This prevents + deserialization of any class except those explicitly permitted, such as + in the following example that restricts deserialization to the Bicycle + class only: + + ``` + // Code from https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html + public class LookAheadObjectInputStream extends ObjectInputStream { + public LookAheadObjectInputStream(InputStream inputStream) throws IOException { + super(inputStream); + } + /** + * Only deserialize instances of our expected Bicycle class + */ + @Override + protected Class resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException { + if (!desc.getName().equals(Bicycle.class.getName())) { + throw new InvalidClassException("Unauthorized deserialization attempt", desc.getName()); + } + return super.resolveClass(desc); + } + } + ``` + metadata: + cwe: "CWE-502" + owasp: + - "A8:2017-Insecure Deserialization" + - "A08:2021-Software and Data Integrity Failures" + category: "security" + shortDescription: "Deserialization of untrusted data" + security-severity: "High" + references: + - "https://www.blackhat.com/docs/us-16/materials/us-16-Kaiser-Pwning-Your-Java-Messaging-With-Deserialization-Vulnerabilities-wp.pdf" + technology: + - "java" + cwe2022-top25: "true" + cwe2021-top25: "true" + subcategory: + - "vuln" + likelihood: "LOW" + impact: "MEDIUM" + confidence: "MEDIUM" + license: "Commons Clause License Condition v1.0[LGPL-2.1-only]" + vulnerability_class: + - "Insecure Deserialization " + severity: "ERROR" +- id: java_deserialization_rule-ServerDangerousObjectDeserialization + languages: + - java + patterns: + - pattern-inside: | + interface $INTERFACE extends Remote { + ... + } + - pattern: | + $RETURNTYPE $METHOD($PARAMTYPE $PARAM) throws RemoteException; + - metavariable-pattern: + metavariable: $PARAMTYPE + language: generic + patterns: + - pattern-not: String + - pattern-not: java.lang.String + - pattern-not: boolean + - pattern-not: Boolean + - pattern-not: java.lang.Boolean + - pattern-not: byte + - pattern-not: Byte + - pattern-not: java.lang.Byte + - pattern-not: char + - pattern-not: Character + - pattern-not: java.lang.Character + - pattern-not: double + - pattern-not: Double + - pattern-not: java.lang.Double + - pattern-not: float + - pattern-not: Float + - pattern-not: java.lang.Float + - pattern-not: int + - pattern-not: Integer + - pattern-not: java.lang.Integer + - pattern-not: long + - pattern-not: Long + - pattern-not: java.lang.Long + - pattern-not: short + - pattern-not: Short + - pattern-not: java.lang.Short + severity: "WARNING" + metadata: + cwe: "CWE-502" + shortDescription: "Deserialization of untrusted data" + owasp: + - "A8:2017-Insecure Deserialization" + - "A08:2021-Software and Data Integrity Failures" + references: + - "https://frohoff.github.io/appseccali-marshalling-pickles/" + - "https://book.hacktricks.xyz/network-services-pentesting/1099-pentesting-java-rmi" + - "https://youtu.be/t_aw1mDNhzI" + - "https://github.com/qtc-de/remote-method-guesser" + - "https://github.com/openjdk/jdk/blob/master/src/java.rmi/share/classes/sun/rmi/server/UnicastRef.java#L303C4-L331" + - "https://mogwailabs.de/en/blog/2019/03/attacking-java-rmi-services-after-jep-290/" + category: "security" + security-severity: "MEDIUM" + technology: + - "rmi" + cwe2022-top25: "true" + cwe2021-top25: "true" + likelihood: "LOW" + impact: "HIGH" + confidence: "LOW" + license: "Commons Clause License Condition v1.0[LGPL-2.1-only]" + vulnerability_class: + - "Insecure Deserialization " + message: | + This application uses Java RMI (Remote Method Invocation) interfaces + that declare methods with parameters of arbitrary objects + ('$PARAMTYPE $PARAM') that could lead to insecure deserialization + vulnerabilities. Insecure deserialization occurs when an application + deserializes data from untrusted sources without proper sanitization, + potentially leading to arbitrary code execution, denial of service attacks, + and other critical vulnerabilities. + + Java RMI allows for remote communication between applications by + invoking methods on remote objects. When complex objects are used + as parameters in RMI method declarations, there is + a risk that a malicious actor could exploit the deserialization + process to execute arbitrary code on the server. This vulnerability + is especially significant if the parameter types are not among the safe, + immutable types like String, Integer, etc. + + To mitigate this vulnerability, use an integer ID to look up your + object, or consider alternative serialization schemes such as JSON. + + Secure Code Example: + ``` + import java.rmi.Remote; + import java.rmi.RemoteException; + + public interface SafeTicketService extends Remote { + // Using String, which is a safe, immutable type + boolean registerTicket(String ticketID) throws RemoteException; + + // Using primitive data types and wrappers, which are safe + void visitTalk(int talkID) throws RemoteException; + void poke(Integer attendeeID) throws RemoteException; + } + ``` +- id: java_deserialization_rule-SnakeYamlConstructor + languages: + - java + patterns: + - pattern: | + $Y = new org.yaml.snakeyaml.Yaml(); + ... + $Y.load(...); + message: | + The application uses SnakeYAML org.yaml.snakeyaml.Yaml() constructor + with no arguments, which is vulnerable to deserialization attacks. + When Yaml() (no-argument constructor) is used, SnakeYAML uses the + default Constructor which can instantiate any Java object during + deserialization. This is risky because an attacker could craft malicious + YAML files to execute arbitrary code or perform unauthorized actions. + + To mitigate the issue and to safely use SnakeYaml to parse YAML data, + always make sure to only ever use a Yaml instance that is constructed + either with a SafeConstructor or an instance constructed with a + Constructor specifying a specific class. + + Please note, if you want to use Constructor with a specific target class + as a mitigation criteria, ensure that snakeyaml version is 2.0 or higher + as Constructor class is vulnerable in snakeyaml versions lower than 2.0. + Refer - https://github.com/google/security-research/security/advisories/GHSA-mjmj-j48q-9wg2 + + Secure Code Examples: + ``` + public void safeConstructorLoad(String toLoad) { + // Configure LoaderOptions for safe deserialization + LoaderOptions loaderOptions = new LoaderOptions(); + loaderOptions.setAllowDuplicateKeys(false); + loaderOptions.setMaxAliasesForCollections(50); + + Yaml yaml = new Yaml(new SafeConstructor(new LoaderOptipon())); + yaml.load(toLoad); + } + + public void customConstructorLoad(String toLoad, Class goodClass) { + // Use Constructor with a specific target class + LoaderOptions loaderOptions = new LoaderOptions(); + Constructor customConstructor = new Constructor(goodClass, loaderOptions); + + Yaml yaml = new Yaml(customConstructor); + yaml.load(toLoad); + } + ``` + metadata: + cwe: "CWE-502" + owasp: + - "A8:2017-Insecure Deserialization" + - "A08:2021-Software and Data Integrity Failures" + category: "security" + shortDescription: "Deserialization of untrusted data" + security-severity: "HIGH" + references: + - "https://securitylab.github.com/research/swagger-yaml-parser-vulnerability/#snakeyaml-deserialization-vulnerability" + technology: + - "snakeyaml" + likelihood: "LOW" + impact: "HIGH" + confidence: "LOW" + severity: "ERROR" +- id: java_endpoint_rule-ManuallyConstructedURLs + languages: + - java + severity: ERROR + message: | + User data flows into the host portion of this manually-constructed URL. + This could allow an attacker to send data to their own server, potentially + exposing sensitive data such as cookies or authorization information sent + with this request. They could also probe internal servers or other + resources that the server running this code can access. (This is called + server-side request forgery, or SSRF.) Do not allow arbitrary hosts. + Instead, create an allowlist for approved hosts hardcode the correct host, + or ensure that the user data can only affect the path or parameters. + + Example of using allowlist: + ``` + ArrayList allowlist = (ArrayList) + Arrays.asList(new String[] { "https://example.com/api/1", "https://example.com/api/2", "https://example.com/api/3"}); + + if(allowlist.contains(url)){ + ... + } + ``` + options: + interfile: true + metadata: + security-severity: CRITICAL + cwe: "CWE-918" + owasp: + - "A1:2017-Injection" + - "A10:2021-Server-Side Request Forgery" + shortDescription: "Detect manually constructed URLs" + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet.html + category: security + technology: + - java + - spring + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + impact: MEDIUM + likelihood: MEDIUM + confidence: MEDIUM + interfile: true + license: Commons Clause License Condition v1.0[LGPL-2.1-only] + vulnerability_class: + - Server-Side Request Forgery (SSRF) + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - pattern-inside: | + $METHODNAME(..., @$REQ(...) $TYPE $SOURCE,...) { + ... + } + - pattern-inside: | + $METHODNAME(..., @$REQ $TYPE $SOURCE,...) { + ... + } + - metavariable-regex: + metavariable: $TYPE + regex: ^(?!(Integer|Long|Float|Double|Char|Boolean|int|long|float|double|char|boolean)) + - metavariable-regex: + metavariable: $REQ + regex: (RequestBody|PathVariable|RequestParam|RequestHeader|CookieValue|ModelAttribute) + - focus-metavariable: $SOURCE + pattern-sinks: + - pattern-either: + - pattern: new URL($ONEARG) + - patterns: + - pattern-either: + - pattern: | + "$URLSTR" + ... + - pattern: | + "$URLSTR".concat(...) + - patterns: + - pattern-inside: | + StringBuilder $SB = new StringBuilder("$URLSTR"); + ... + - pattern: $SB.append(...) + - patterns: + - pattern-inside: | + $VAR = "$URLSTR"; + ... + - pattern: $VAR += ... + - patterns: + - pattern: String.format("$URLSTR", ...) + - pattern-not: String.format("$URLSTR", "...", ...) + - patterns: + - pattern-inside: | + String $VAR = "$URLSTR"; + ... + - pattern: String.format($VAR, ...) + - metavariable-regex: + metavariable: $URLSTR + regex: http(s?)://%(v|s|q).* + pattern-sanitizers: + - patterns: + - pattern-either: + - pattern: | + if($VALIDATION){ + ... + new URL($ONEARG); + ... + } + - pattern: | + $A = $VALIDATION; + ... + if($A){ + ... + new URL($ONEARG); + ... + } + - metavariable-pattern: + metavariable: $VALIDATION + pattern-either: + - pattern: | + $AL.contains(...) + - pattern: | + $AL.indexOf(...) != -1 +- id: java_file_rule_rule-FilePathTraversalHttpServlet + languages: + - "java" + severity: ERROR + metadata: + security-severity: CRITICAL + shortDescription: "Improper Limitation of a Pathname to a Restricted Directory + ('Path Traversal')" + cwe: "CWE-22" + owasp: + - "A5:2017-Broken Access Control" + - "A01:2021-Broken Access Control" + source-rule-url: https://find-sec-bugs.github.io/bugs.htm#PATH_TRAVERSAL_IN + references: + - https://www.owasp.org/index.php/Path_Traversal + category: "security" + technology: + - "java" + cwe2022-top25: true + cwe2021-top25: true + impact: MEDIUM + confidence: MEDIUM + license: Commons Clause License Condition v1.0[LGPL-2.1-only] + vulnerability_class: + - Path Traversal + message: | + Detected a potential path traversal. A malicious actor could control + the location of this file, to include going backwards in the directory + with '../'. + + To address this, ensure that user-controlled variables in file + paths are sanitized. You may also consider using a utility method such as + org.apache.commons.io.FilenameUtils.getName(...) to only retrieve the file + name from the path. + + Example code using FilenameUtils.getName(...) + + ``` + public void ok(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + String image = request.getParameter("image"); + File file = new File("static/images/", FilenameUtils.getName(image)); + + if (!file.exists()) { + log.info(image + " could not be created."); + response.sendError(); + } + + response.sendRedirect("/index.html"); + } + ``` + mode: "taint" + pattern-sources: + - patterns: + - pattern-either: + - pattern: | + (HttpServletRequest $REQ) + - patterns: + - pattern-inside: > + (javax.servlet.http.Cookie[] $COOKIES) = + (HttpServletRequest $REQ).getCookies(...); + ... + + for (javax.servlet.http.Cookie $COOKIE: $COOKIES) { + ... + } + - pattern: | + $COOKIE.getValue(...) + - patterns: + - pattern-inside: | + $TYPE[] $VALS = (HttpServletRequest $REQ).$GETFUNC(...); + ... + - pattern: | + $PARAM = $VALS[$INDEX]; + pattern-sanitizers: + - pattern: org.apache.commons.io.FilenameUtils.getName(...) + pattern-sinks: + - patterns: + - pattern-either: + - pattern: | + (java.io.File $FILE) = ... + - pattern: | + (java.io.FileOutputStream $FOS) = ... + - pattern: | + new java.io.FileInputStream(...) +- id: java_ftp_rule-FTPInsecureTransport + message: | + This rule identifies instances where the application uses FTP (File + Transfer Protocol) for transferring files. FTP transmits data in clear + text, allowing usernames, passwords, and other sensitive information to be + intercepted by attackers. Consider using secure alternatives like SFTP + (SSH File Transfer Protocol) or FTPS (FTP Secure) that provide encryption + to protect data in transit. + + Remediation Strategy: To mitigate the risks associated with using unencrypted + FTP, the application should switch to a secure file transfer protocol like + SFTP or FTPS. Below is an example of how to implement FTPS in a Java + application. + + ``` + import org.apache.commons.net.ftp.FTPSClient; + + public class FTPSExample { + public static void main(String[] args) { + String server = "ftps.example.com"; + int port = 21; + String user = "your_username"; + String pass = "your_password"; + + FTPSClient ftpsClient = new FTPSClient(); + try { + ftpsClient.connect(server, port); + ftpsClient.login(user, pass); + // Perform file operations + + ftpsClient.logout(); + ftpsClient.disconnect(); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + ``` + severity: WARNING + metadata: + security-severity: MEDIUM + shortDescription: Cleartext transmission of sensitive information + category: security + cwe: CWE-319 + owasp: + - A3:2017-Sensitive Data Exposure + - A02:2021-Cryptographic Failures + references: + - https://www.codejava.net/java-se/ftp/connect-and-login-to-a-ftp-server + - https://commons.apache.org/proper/commons-net/apidocs/org/apache/commons/net/ftp/FTPClient.html + subcategory: + - vuln + technology: + - java + vulnerability: Insecure Transport + license: Commons Clause License Condition v1.0[LGPL-2.1-only] + languages: + - java + pattern-either: + - pattern: | + (org.apache.commons.net.ftp.FTPClient $FTPCLIENT).connect(...); + - pattern: | + URL $URL = new URL("=~/^[fF][tT][pP]://.*/"); + ... + URLConnection $CONN = $URL.openConnection(...); +- id: java_inject_rule-DangerousGroovyShell + languages: + - java + patterns: + - pattern-either: + - pattern: | + (groovy.lang.GroovyShell $SHELL).parse(...) + - pattern: | + (groovy.lang.GroovyShell $SHELL).evaluate(...) + - pattern: | + (groovy.lang.GroovyClassLoader $SHELL).parseClass(...) + - pattern-not: | + $SHELL.parse("...",...) + - pattern-not: | + $SHELL.evaluate("...",...) + - pattern-not: | + $SHELL.parseClass("...",...) + - pattern-not-inside: | + if($ALLOWLIST.contains($INPUT)){ + ... + } + message: | + This application implements unsafe invocations of methods within the + `groovy.lang.GroovyShell` or `groovy.lang.GroovyClassLoader` classes, + which are used to evaluate or compile Groovy code dynamically. When + user-controlled input is directly passed to `parse`, `evaluate`, or + `parseClass` methods, it can lead to Remote Code Execution (RCE), where an + attacker can execute arbitrary code on the server. This could potentially + allow an attacker to gain unauthorized access to system resources, modify + internal application states, or execute commands on the server depending + on the level of permissions assigned to the application process. + + To mitigate this vulnerability, always validate and sanitize all user inputs + before using them in dynamic code evaluations. Consider using safer alternatives + to executing dynamic code if possible. If dynamic code execution is absolutely + necessary, use strict allowlists of safe inputs and context-specific validation. + + Secure Code Example: + + ``` + import groovy.lang.GroovyShell; + + class SafeDynamicEvaluation { + private static final Set ALLOWED_EXPRESSIONS = new HashSet<>(Arrays.asList( + "println 'Hello World!'", + "println 'Goodbye World!'")); + + public static void test4(String[] args, ClassLoader loader) throws Exception { + GroovyShell shell = new GroovyShell(); + String userInput = args[0]; + + // Validate the user input against the allowlist + if (ALLOWED_EXPRESSIONS.contains(userInput)) { + shell.evaluate(userInput); + // shell.parse(userInput); + } else { + throw new IllegalArgumentException("Invalid or unauthorized command."); + } + } + } + ``` + metadata: + shortDescription: "Improper control of generation of code ('Code Injection')" + category: "security" + cwe: "CWE-94" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "CRITICAL" + source-rule-url: "https://find-sec-bugs.github.io/bugs.htm#GROOVY_SHELL" + technology: + - "groovy" + references: + - "https://owasp.org/Top10/A03_2021-Injection" + cwe2022-top25: "true" + license: "Commons Clause License Condition v1.0[LGPL-2.1-only]" + vulnerability_class: + - "Code Injection" + severity: "ERROR" +- id: java_inject_rule-EnvInjection + message: | + Detected input from a HTTPServletRequest going into the environment + variables of an 'exec' command. The user input is passed directly to + the Runtime.exec() function to set an environment variable. This allows + malicious input from the user to modify the command that will be executed. + To remediate this, do not pass user input directly to Runtime.exec(). + Validate any user input before using it to set environment variables + or command arguments. Consider using an allow list of allowed values + rather than a deny list. If dynamic commands must be constructed, use + a map to look up valid values based on user input instead of using + the input directly. + Example of safely executing an OS command: + ``` + public void doPost(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + response.setContentType("text/html;charset=UTF-8"); + + String param = ""; + if (request.getHeader("UserDefined") != null) { + param = request.getHeader("UserDefined"); + } + + param = java.net.URLDecoder.decode(param, "UTF-8"); + String cmd = "/bin/cmd"; + + String[] allowList = {"FOO=true","FOO=false","BAR=true", "BAR=false"} + if(Arrays.asList(allowList).contains(param)){ + String[] argsEnv = {param}; + } + + Runtime r = Runtime.getRuntime(); + + try { + Process p = r.exec(cmd, argsEnv); + printOSCommandResults(p, response); + } catch (IOException e) { + System.out.println("Problem executing command"); + response.getWriter() + .println(org.owasp.esapi.ESAPI.encoder().encodeForHTML(e.getMessage())); + return; + } + ``` + languages: + - "java" + severity: "ERROR" + mode: "taint" + pattern-sources: + - patterns: + - pattern-either: + - pattern: | + (HttpServletRequest $REQ) + - patterns: + - pattern-inside: | + $FUNC(..., $VAR, ...) { + ... + } + - pattern: $VAR + pattern-sinks: + - pattern-either: + - patterns: + - pattern: (java.lang.Runtime $R).exec($CMD, $ENV_ARGS, ...); + - focus-metavariable: $ENV_ARGS + - patterns: + - pattern: (ProcessBuilder $PB).environment().put($...ARGS); + - focus-metavariable: $...ARGS + - patterns: + - pattern: | + $ENV = (ProcessBuilder $PB).environment(); + ... + $ENV.put($...ARGS); + - focus-metavariable: $...ARGS + pattern-sanitizers: + - patterns: + - pattern-either: + - pattern: | + if($VALIDATION){ + ... + } + - patterns: + - pattern-inside: | + $A = $VALIDATION; + ... + - pattern: | + if($A){ + ... + } + - metavariable-pattern: + metavariable: $VALIDATION + pattern-either: + - pattern: | + $AL.contains(...) + metadata: + shortDescription: + "Improper neutralization of special elements used in an OS + command ('OS Command Injection')" + category: "security" + technology: + - "java" + cwe: CWE-78 + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + references: + - "https://owasp.org/Top10/A03_2021-Injection" + subcategory: + - "vuln" + likelihood: "MEDIUM" + impact: "MEDIUM" + confidence: "MEDIUM" + license: "Commons Clause License Condition v1.0[LGPL-2.1-only]" + vulnerability_class: + - "Other" + security-severity: "HIGH" +- id: java_inject_rule-MongodbNoSQLi + languages: + - java + patterns: + - pattern-either: + - pattern: (com.mongodb.BasicDBObject $QUERY).put("$where", $INPUT); + - pattern: | + (HashMap $MAP).put("$where", $INPUT); + ... + (com.mongodb.BasicDBObject $QUERY).putAll($MAP); + - pattern: (com.mongodb.BasicDBObject $QUERY).append("$where", $INPUT); + - pattern: new com.mongodb.BasicDBObject("$where", $INPUT); + - pattern: | + (HashMap $MAP).put("$where", $INPUT); + ... + new com.mongodb.BasicDBObject($MAP); + - pattern: | + (HashMap $MAP).put("$where", $INPUT); + ... + String json = new JSONObject($MAP).toString(); + ... + (com.mongodb.BasicDBObject $QUERY).parse((String $JSON)); + - pattern: com.mongodb.BasicDBObjectBuilder.start().add("$where", $INPUT); + - pattern: com.mongodb.BasicDBObjectBuilder.start().append("$where", $INPUT); + - pattern: com.mongodb.BasicDBObjectBuilder.start("$where", $INPUT); + - pattern: | + (HashMap $MAP).put("$where", $INPUT); + ... + com.mongodb.BasicDBObjectBuilder.start($MAP); + - metavariable-pattern: + metavariable: $INPUT + patterns: + - pattern: | + ... + - pattern-not: | + "..." + message: | + Detected non-constant data passed into a NoSQL query using the 'where' + evaluation operator. If this data can be controlled by an external user, + this is a NoSQL injection. Ensure data passed to the NoSQL query is not + user controllable, or properly sanitize the data. Ideally, avoid using the + 'where' operator at all and instead use the helper methods provided by + com.mongodb.client.model.Filters with comparative operators such as eq, + ne, lt, gt, etc. + + Secure Code Example: + ``` + MongoDatabase database = mongoClient.getDatabase("mydb"); + MongoCollection collection = database.getCollection("users"); + + // Secure usage with Filters.eq: + String username = request.getParameter("username"); + collection.find(Filters.eq("username", username)); + ``` + severity: "ERROR" + metadata: + category: "security" + technology: + - "nosql" + - "mongodb" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + cwe: "CWE-943" + shortDescription: "Improper neutralization of special elements in data query logic" + security-severity: "CRITICAL" + references: + - "https://owasp.org/Top10/A03_2021-Injection" + - "https://www.mongodb.com/docs/manual/tutorial/query-documents/" + - "https://www.mongodb.com/docs/manual/reference/operator/query/where/" + subcategory: + - "audit" + likelihood: "LOW" + impact: "HIGH" + confidence: "LOW" + license: "Commons Clause License Condition v1.0[LGPL-2.1-only]" + vulnerability_class: + - "Improper Validation" +- id: java_inject_rule-SeamLogInjection + languages: + - "java" + patterns: + - pattern: | + $LOG.$INFO($X + $Y,...) + - pattern-either: + - pattern-inside: | + import org.jboss.seam.log.Log; + ... + - pattern-inside: | + org.jboss.seam.log.Log $LOG = ...; + ... + - metavariable-regex: + metavariable: $INFO + regex: (debug|error|fatal|info|trace|warn) + message: | + The Seam logging API supports an expression language that allows developers to + introduce bean properties to log messages. The expression language can also be + the source to unwanted code execution. Expressions could be executed by dynamically + inserting user-controlled input into the various logging calls. + + Use the [Seam logging API format specifier](https://docs.jboss.org/seam/2.1.2/reference/en-US/html/concepts.html#d0e4244) to ensure values are logged and expressions + are not executed dynamically prior to output. + + Example logging call that safely logs the unfiltered values. + ``` + log.info("This is a user controlled input = #0", input); + ``` + severity: "ERROR" + metadata: + category: "security" + shortDescription: "Improper neutralization of directives in dynamically + evaluated code ('Eval Injection')" + cwe: "CWE-95" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + references: + - "https://owasp.org/Top10/A03_2021-Injection" + license: "Commons Clause License Condition v1.0[LGPL-2.1-only]" + security-severity: "CRITICAL" +- id: java_inject_rule-SqlInjection + languages: + - "java" + options: + taint_assume_safe_booleans: true + taint_assume_safe_numbers: true + message: | + SQL Injection is a critical vulnerability that can lead to data or system compromise. By + dynamically generating SQL query strings, user input may be able to influence the logic of + the SQL statement. This could lead to an adversary accessing information they should + not have access to, or in some circumstances, being able to execute OS functionality or code. + + Replace all dynamically generated SQL queries with parameterized queries. In situations where + dynamic queries must be created, never use direct user input, but instead use a map or + dictionary of valid values and resolve them using a user-supplied key. + + For example, some database drivers do not allow parameterized queries for `>` or `<` comparison + operators. In these cases, do not use a user supplied `>` or `<` value, but rather have the + user + supply a `gt` or `lt` value. The alphabetical values are then used to look up the `>` and `<` + values to be used in the construction of the dynamic query. The same goes for other queries + where + column or table names are required but cannot be parameterized. + + Example using `PreparedStatement` queries: + ``` + // Some userInput + String userInput = "someUserInput"; + // Your connection string + String url = "..."; + // Get a connection from the DB via the DriverManager + Connection conn = DriverManager.getConnection(url); + // Create a prepared statement + PreparedStatement st = conn.prepareStatement("SELECT name FROM table where name=?"); + // Set each parameters value by the index (starting from 1) + st.setString(1, userInput); + // Execute query and get the result set + ResultSet rs = st.executeQuery(); + // Iterate over results + while (rs.next()) { + // Get result for this row at the provided column number (starting from 1) + String result = rs.getString(1); + // ... + } + // Close the ResultSet + rs.close(); + // Close the PreparedStatement + st.close(); + ``` + + Example on using CriteriaBuilder to build queries + ``` + public List findBySomeCriteria(EntityManager entityManager, String criteriaValue) { + CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); + CriteriaQuery query = criteriaBuilder.createQuery(YourEntity.class); + Root root = query.from(YourEntity.class); + + query.select(root).where(criteriaBuilder.equal(root.get("someProperty"), criteriaValue)); + + return entityManager.createQuery(query).getResultList(); + } + ``` + + For more information on SQL Injection see OWASP: + https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html + mode: taint + pattern-sources: + - pattern: (javax.servlet.http.HttpServletRequest $R).$METHOD(...) + - pattern: (java.util.Scanner $S).$METHOD(...) + - pattern: (java.util.stream.Stream).$METHOD(...) + - pattern: (java.util.StringJoiner $SJ).toString(...) + - pattern: (java.sql.ResultSet.getString $R).$METHOD(...) + - pattern: (java.lang.System $S).getProperty(...) + - pattern: (java.lang.System $S).getenv(...) + - pattern: (java.lang.StringBuilder $SB).toString(...) + - pattern: (java.io.FileInputStream $F).read(...) + - pattern: (java.io.FileReader $F).read(...) + - pattern: (java.net.Socket $S).getInputStream(...) + - pattern: (java.net.Socket $S).getOutputStream(...) + - pattern: (java.net.DatagramSocket $S).receive(...) + - pattern: (java.net.DatagramSocket $S).getInputStream(...) + - pattern: java.nio.file.Files.readAllBytes(...) + - pattern: java.nio.file.Files.readAllLines(...) + - pattern: java.nio.file.Files.lines(...) + - pattern: java.nio.file.Files.newBufferedReader(...) + - pattern: org.apache.commons.io.IOUtils.toString(...) + - pattern: org.apache.commons.io.IOUtils.readLines(...) + - pattern: org.apache.commons.io.IOUtils.toByteArray(...) + - pattern: (com.fasterxml.jackson.databind.ObjectMapper $OM).readValue(...) + - pattern: (com.fasterxml.jackson.databind.ObjectMapper $OM).treeToValue(...) + - pattern: $CLASS.$METHOD(..., (javax.servlet.http.HttpServletRequest $R), ...) + - pattern: $FUNC(..., (javax.servlet.http.HttpServletRequest $R), ...) + - patterns: + - pattern-inside: + $FUNC(..., String $X, ...) { ... } + - focus-metavariable: $X + pattern-propagators: + - pattern: $LIST.add($X) + from: $X + to: $LIST + - pattern: $MAP.put(..., $X) + from: $X + to: $MAP + - pattern: $STR.concat($X) + from: $X + to: $STR + - pattern: $STR = String.format(..., $X, ...) + from: $X + to: $STR + - pattern: $STR = String.join(..., $X, ...) + from: $X + to: $STR + - pattern: $SB.append($X) + from: $X + to: $SB + pattern-sinks: + - patterns: + - pattern-either: + - pattern: (javax.jdo.PersistenceManager $PM).newQuery($ARG) + - pattern: (javax.jdo.PersistenceManager $PM).newQuery(..., $ARG) + - pattern: (javax.jdo.Query $Q).setFilter($ARG) + - pattern: (javax.jdo.Query $Q).setGrouping($ARG) + - pattern: org.hibernate.criterion.Restrictions.sqlRestriction($ARG, ...) + - pattern: (org.hibernate.Session $S).createQuery((String $ARG), ...) + - pattern: (org.hibernate.Session $S).createSQLQuery($ARG, ...) + - pattern: (org.hibernate.Session $S).connection().prepareStatement($ARG) + - pattern: (java.sql.Statement $S).executeQuery($ARG, ...) + - pattern: (java.sql.Statement $S).execute($ARG, ...) + - pattern: (java.sql.Statement $S).executeUpdate($ARG, ...) + - pattern: (java.sql.Statement $S).executeLargeUpdate($ARG, ...) + - pattern: (java.sql.Statement $S).addBatch($ARG, ...) + - pattern: (java.sql.PreparedStatement $S).executeQuery($ARG, ...) + - pattern: (java.sql.PreparedStatement $S).execute($ARG, ...) + - pattern: (java.sql.PreparedStatement $S).executeUpdate($ARG, ...) + - pattern: (java.sql.PreparedStatement $S).executeLargeUpdate($ARG, ...) + - pattern: (java.sql.PreparedStatement $S).addBatch($ARG, ...) + - pattern: (java.sql.Connection $S).prepareCall($ARG, ...) + - pattern: (java.sql.Connection $S).prepareStatement($ARG, ...) + - pattern: (java.sql.Connection $S).nativeSQL($ARG, ...) + - pattern: new org.springframework.jdbc.core.PreparedStatementCreatorFactory($ARG, ...) + - pattern: (org.springframework.jdbc.core.PreparedStatementCreatorFactory $F).newPreparedStatementCreator($ARG, ...) + - pattern: (org.springframework.jdbc.core.JdbcOperations $O).batchUpdate($ARG, ...) + - pattern: (org.springframework.jdbc.core.JdbcOperations $O).execute($ARG, ...) + - pattern: (org.springframework.jdbc.core.JdbcOperations $O).query($ARG, ...) + - pattern: (org.springframework.jdbc.core.JdbcOperations $O).queryForList($ARG, ...) + - pattern: (org.springframework.jdbc.core.JdbcOperations $O).queryForMap($ARG, ...) + - pattern: (org.springframework.jdbc.core.JdbcOperations $O).queryForObject($ARG, ...) + - pattern: (org.springframework.jdbc.core.JdbcOperations $O).queryForObject($ARG, ...) + - pattern: (org.springframework.jdbc.core.JdbcOperations $O).queryForRowSet($ARG, ...) + - pattern: (org.springframework.jdbc.core.JdbcOperations $O).queryForInt($ARG, ...) + - pattern: (org.springframework.jdbc.core.JdbcOperations $O).queryForLong($ARG, ...) + - pattern: (org.springframework.jdbc.core.JdbcOperations $O).update($ARG, ...) + - pattern: (org.springframework.jdbc.core.JdbcTemplate $O).batchUpdate($ARG, ...) + - pattern: (org.springframework.jdbc.core.JdbcTemplate $O).execute($ARG, ...) + - pattern: (org.springframework.jdbc.core.JdbcTemplate $O).query($ARG, ...) + - pattern: (org.springframework.jdbc.core.JdbcTemplate $O).queryForList($ARG, ...) + - pattern: (org.springframework.jdbc.core.JdbcTemplate $O).queryForMap($ARG, ...) + - pattern: (org.springframework.jdbc.core.JdbcTemplate $O).queryForObject($ARG, ...) + - pattern: (org.springframework.jdbc.core.JdbcTemplate $O).queryForRowSet($ARG, ...) + - pattern: (org.springframework.jdbc.core.JdbcTemplate $O).queryForInt($ARG, ...) + - pattern: (org.springframework.jdbc.core.JdbcTemplate $O).queryForLong($ARG, ...) + - pattern: (org.springframework.jdbc.core.JdbcTemplate $O).update($ARG, ...) + - pattern: (io.vertx.sqlclient.SqlClient $O).query($ARG, ...) + - pattern: (io.vertx.sqlclient.SqlClient $O).preparedQuery($ARG, ...) + - pattern: (io.vertx.sqlclient.SqlConnection $O).prepare($ARG, ...) + - pattern: (org.apache.turbine.om.peer.BasePeer $O).executeQuery($ARG, ...) + - pattern: org.apache.torque.util.BasePeer.executeQuery($ARG, ...) + - pattern: org.apache.torque.util.BasePeer.executeStatement($ARG, ...) + - pattern: (javax.persistence.EntityManager $O).createQuery($ARG, ...) + - pattern: (javax.persistence.EntityManager $O).createNativeQuery($ARG, ...) + - pattern: (org.jdbi.v3.core.Handle $H).createQuery($ARG, ...) + - pattern: (org.jdbi.v3.core.Handle $H).createScript($ARG, ...) + - pattern: (org.jdbi.v3.core.Handle $H).createUpdate($ARG, ...) + - pattern: (org.jdbi.v3.core.Handle $H).execute($ARG, ...) + - pattern: (org.jdbi.v3.core.Handle $H).prepareBatch($ARG, ...) + - pattern: (org.jdbi.v3.core.Handle $H).select($ARG, ...) + - pattern: new org.jdbi.v3.core.statement.Script($H, $ARG) + - pattern: new org.jdbi.v3.core.statement.Update($H, $ARG) + - pattern: new org.jdbi.v3.core.statement.PreparedBatch($H, $ARG) + - focus-metavariable: $ARG + - patterns: + - pattern: (java.sql.Connection $S).createStatement(...).$SQLFUNC($ARG, ...) + - pattern-not: (java.sql.Connection $S).createStatement(...).$SQLFUNC("...") + - metavariable-regex: + metavariable: $SQLFUNC + regex: execute|executeQuery|createQuery|query|addBatch|nativeSQL|create|prepare + pattern-sanitizers: + - pattern: (CriteriaBuilder $CB).$ANY(...) + metadata: + shortDescription: "Improper neutralization of special elements used in an SQL command ('SQL Injection')" + category: "security" + cwe: "CWE-89" + technology: + - "java" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "High" + severity: "ERROR" +- id: java_traversal_rule-RelativePathTraversal + languages: + - "java" + message: | + Detected user input controlling a file path. An attacker could control + the location of this file, to include going backwards in the directory + with '../'. + + To address this, ensure that user-controlled variables in file + paths are sanitized. You may also consider using a utility method such as + org.apache.commons.io.FilenameUtils.getName(...) to only retrieve the file + name from the path. + + Example of using `org.apache.commons.io.FilenameUtils.getName(...)` to + only retrieve the file name from the path + ``` + String fileName = org.apache.commons.io.FilenameUtils.getName(userControlledInput); + File file = new File("/path/to/directory/" + fileName); + ``` + options: + interfile: true + severity: ERROR + metadata: + cwe: "CWE-23" + shortDescription: "Relative Path Traversal" + owasp: + - "A01:2021-Broken Access Control" + - "A5:2017-Broken Access Control" + references: + - https://owasp.org/www-community/attacks/Path_Traversal + category: "security" + security-severity: "CRITICAL" + license: "Commons Clause License Condition v1.0[LGPL-2.1-only]" + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - pattern-inside: | + $METHODNAME(..., @$REQ(...) $TYPE $SOURCE,...) { + ... + } + - pattern-inside: | + $METHODNAME(..., @$REQ $TYPE $SOURCE,...) { + ... + } + - metavariable-regex: + metavariable: $TYPE + regex: ^(?!(Integer|Long|Float|Double|Char|Boolean|int|long|float|double|char|boolean)) + - metavariable-regex: + metavariable: $REQ + regex: (RequestBody|PathVariable|RequestParam|RequestHeader|CookieValue|ModelAttribute) + - focus-metavariable: $SOURCE + pattern-sinks: + - patterns: + - pattern-either: + - pattern: new File(...) + - pattern: new java.io.File(...) + - pattern: new FileReader(...) + - pattern: new java.io.FileReader(...) + - pattern: new FileInputStream(...) + - pattern: new java.io.FileInputStream(...) + - pattern: (Paths $PATHS).get(...) + - patterns: + - pattern: | + $CLASS.$FUNC(...) + - metavariable-regex: + metavariable: $FUNC + regex: ^(getResourceAsStream|getResource)$ + - patterns: + - pattern-either: + - pattern: new ClassPathResource($FILE, ...) + - pattern: ResourceUtils.getFile($FILE, ...) + - pattern: new FileOutputStream($FILE, ...) + - pattern: new java.io.FileOutputStream($FILE, ...) + - pattern: new StreamSource($FILE, ...) + - pattern: new javax.xml.transform.StreamSource($FILE, ...) + - pattern: FileUtils.openOutputStream($FILE, ...) + - focus-metavariable: $FILE + pattern-sanitizers: + - pattern: org.apache.commons.io.FilenameUtils.getName(...) +- id: java_xpathi_rule-XpathInjection + languages: + - "java" + message: | + The application processes `XPath` queries with potentially malicious input. + An adversary who is able to control the XPath query could potentially influence the logic + of how data is retrieved, processed or even bypass protections. + + To mitigate the vulnerability, avoid using user input in XPath queries. + If it cannot be avoided, validate the user input against an allowlist + of expected values before using it in the query. + + Following is an example that demonstrates how to perform an XPath query + using user input validated against an allowlist. + + Secure code example: + ``` + public class SecureXPathWithoutResolver { + + private static final List ALLOWED_AUTHORS = List.of("Author1", "Author2", "Author3"); + + public static void main(String[] args) { + try { + String userInput = "Author1"; // Example user input + if (ALLOWED_AUTHORS.contains(userInput)) { + // User input is safe to use + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + DocumentBuilder builder = factory.newDocumentBuilder(); + Document doc = builder.parse("path/to/your/xmlfile.xml"); + + XPathFactory xpathFactory = XPathFactory.newInstance(); + XPath xpath = xpathFactory.newXPath(); + + // Safely embed the validated user input into the XPath expression + String expression = String.format("//books/book[author='%s']", userInput); + NodeList nodes = (NodeList) xpath.evaluate(expression, doc, XPathConstants.NODESET); + + for (int i = 0; i < nodes.getLength(); i++) { + System.out.println(nodes.item(i).getTextContent()); + } + } else { + throw new IllegalArgumentException("Input is not allowed."); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + } + ``` + + For more information on XPath Injection see: + - https://owasp.org/www-community/attacks/XPATH_Injection + metadata: + shortDescription: + "Improper neutralization of data within XPath expressions ('XPath + Injection')" + category: "security" + cwe: "CWE-643" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "Medium" + mode: "taint" + pattern-sources: + - pattern-either: + - pattern: | + (HttpServletRequest $REQ).$FUNC(...) + - patterns: + - pattern-inside: | + $FUNC(..., $VAR, ...) { + ... + } + - pattern: "$VAR" + pattern-sinks: + - pattern-either: + - patterns: + - pattern-inside: | + (javax.xml.xpath.XPath $XP). ... .evaluate($EXP, ...); + - pattern: "$EXP" + - patterns: + - pattern-inside: | + (javax.xml.xpath.XPath $XP). ... .compile($EXP, ...); + - pattern: "$EXP" + pattern-sanitizers: + - patterns: + - pattern-inside: $MAP.getOrDefault($VAR,"..."); + - pattern: $VAR + - patterns: + - pattern-either: + - pattern: | + if($VALIDATION){ + ... + } + - patterns: + - pattern-inside: | + $A = $VALIDATION; + ... + - pattern: | + if($A){ + ... + } + - metavariable-pattern: + metavariable: $VALIDATION + pattern-either: + - pattern: | + $AL.contains(...) + - pattern: | + $AL.equals(...) + severity: "ERROR" +- id: java_xxe_rule-DisallowDoctypeDeclFalse + severity: "WARNING" + languages: + - "java" + metadata: + cwe: "CWE-611" + shortDescription: "Improper restriction of XML external entity reference" + owasp: + - "A4:2017-XML External Entities (XXE)" + - "A05:2021-Security Misconfiguration" + security-severity: "MEDIUM" + references: + - "https://semgrep.dev/blog/2022/xml-security-in-java" + - "https://semgrep.dev/docs/cheat-sheets/java-xxe/" + - "https://blog.sonarsource.com/secure-xml-processor" + - "https://xerces.apache.org/xerces2-j/features.html" + category: "security" + technology: + - "java" + - "xml" + cwe2022-top25: "true" + cwe2021-top25: "true" + likelihood: "LOW" + impact: "HIGH" + confidence: "HIGH" + license: "Commons Clause License Condition v1.0[LGPL-2.1-only]" + vulnerability_class: + - "XML Injection" + message: | + DOCTYPE declarations are enabled for $DBFACTORY. Without prohibiting + external entity declarations, this is vulnerable to XML external entity + attacks. In an XXE attack, an attacker can exploit the processing of external + entity references within an XML document to access internal files, conduct + denial-of-service attacks, or SSRF (Server Side Request Forgery), potentially + leading to sensitive information disclosure or system compromise. + + To mitigate this vulnerability, disable this by setting the feature + "http://apache.org/xml/features/disallow-doctype-decl" to true. + Alternatively, allow DOCTYPE declarations and only prohibit external + entities declarations. This can be done by setting the features + "http://xml.org/sax/features/external-general-entities" and + "http://xml.org/sax/features/external-parameter-entities" to false. + + Secure Code Example: + ``` + public void GoodXMLInputFactory() throws ParserConfigurationException { + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + } + ``` + patterns: + - pattern: | + $DBFACTORY.setFeature("http://apache.org/xml/features/disallow-doctype-decl", + false); + - pattern-not-inside: > + $RETURNTYPE $METHOD(...){ + ... + $DBF.setFeature("http://xml.org/sax/features/external-general-entities", false); + ... + $DBF.setFeature("http://xml.org/sax/features/external-parameter-entities", false); + ... + } + - pattern-not-inside: > + $RETURNTYPE $METHOD(...){ + ... + $DBF.setFeature("http://xml.org/sax/features/external-parameter-entities", false); + ... + $DBF.setFeature("http://xml.org/sax/features/external-general-entities", false); + ... + } + - pattern-not-inside: | + $RETURNTYPE $METHOD(...){ + ... + $DBF.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, ""); + ... + $DBF.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, ""); + ... + } + - pattern-not-inside: | + $RETURNTYPE $METHOD(...){ + ... + $DBF.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, ""); + ... + $DBF.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, ""); + ... + } + +- id: java_xxe_rule-DocumentBuilderFactoryDisallowDoctypeDeclMissing + severity: "WARNING" + languages: + - "java" + metadata: + cwe: "CWE-611" + shortDescription: "Improper restriction of XML external entity reference" + owasp: + - "A4:2017-XML External Entities (XXE)" + - "A05:2021-Security Misconfiguration" + references: + - "https://semgrep.dev/blog/2022/xml-security-in-java" + - "https://semgrep.dev/docs/cheat-sheets/java-xxe/" + - "https://blog.sonarsource.com/secure-xml-processor" + - "https://xerces.apache.org/xerces2-j/features.html" + category: "security" + security-severity: "MEDIUM" + technology: + - "java" + - "xml" + cwe2022-top25: "true" + cwe2021-top25: "true" + subcategory: + - "vuln" + likelihood: "LOW" + impact: "HIGH" + confidence: "HIGH" + license: "Commons Clause License Condition v1.0[LGPL-2.1-only]" + vulnerability_class: + - "XML Injection" + message: | + DOCTYPE declarations are enabled for this DocumentBuilderFactory. Enabling + DOCTYPE declarations without proper restrictions can make your application + vulnerable to XML External Entity (XXE) attacks. + In an XXE attack, an attacker can exploit the processing of external entity + references within an XML document to access internal files, conduct + denial-of-service attacks, or SSRF (Server Side Request Forgery), potentially + leading to sensitive information disclosure or system compromise. + + To mitigate this vulnerability, disable this by setting the + feature "http://apache.org/xml/features/disallow-doctype-decl" to true. + Alternatively, allow DOCTYPE declarations and only prohibit external + entities declarations. This can be done by setting the features + "http://xml.org/sax/features/external-general-entities" and + "http://xml.org/sax/features/external-parameter-entities" to false. + + Secure Code Example (You can do either of the following): + ``` + public void GoodDocumentBuilderFactory() throws ParserConfigurationException { + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + dbf.newDocumentBuilder(); + } + + public void GoodDocumentBuilderFactory2() throws ParserConfigurationException { + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false); + dbf.setFeature("http://xml.org/sax/features/external-general-entities", false); + dbf.newDocumentBuilder(); + } + ``` + mode: taint + pattern-sources: + - by-side-effect: true + patterns: + - pattern: | + $FACTORY + - pattern-inside: | + $FACTORY = DocumentBuilderFactory.newInstance(); + - pattern-not-inside: > + class $C { + ... + $V $FACTORY = DocumentBuilderFactory.newInstance(); + ... + static { + ... + $FACTORY.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + ... + } + ... + } + - pattern-not-inside: > + class $C { + ... + $V $FACTORY = DocumentBuilderFactory.newInstance(); + ... + static { + ... + $FACTORY.setFeature("http://xml.org/sax/features/external-parameter-entities", false); + ... + $FACTORY.setFeature("http://xml.org/sax/features/external-general-entities", false); + ... + } + ... + } + - pattern-not-inside: > + class $C { + ... + $V $FACTORY = DocumentBuilderFactory.newInstance(); + ... + static { + ... + $FACTORY.setFeature("http://xml.org/sax/features/external-general-entities", false); + ... + $FACTORY.setFeature("http://xml.org/sax/features/external-parameter-entities", false); + ... + } + ... + } + pattern-sinks: + - patterns: + - pattern: | + $FACTORY.newDocumentBuilder(); + pattern-sanitizers: + - by-side-effect: true + pattern-either: + - patterns: + - pattern-either: + - pattern: > + $FACTORY.setFeature("http://apache.org/xml/features/disallow-doctype-decl", + true); + - pattern: > + $FACTORY.setFeature("http://xml.org/sax/features/external-general-entities", + false); + ... + $FACTORY.setFeature("http://xml.org/sax/features/external-parameter-entities", false); + - pattern: > + $FACTORY.setFeature("http://xml.org/sax/features/external-parameter-entities", + false); + ... + $FACTORY.setFeature("http://xml.org/sax/features/external-general-entities", false); + - focus-metavariable: $FACTORY + - patterns: + - pattern-either: + - pattern-inside: > + class $C { + ... + $T $M(...) { + ... + $FACTORY.setFeature("http://apache.org/xml/features/disallow-doctype-decl", + true); + ... + } + ... + } + - pattern-inside: > + class $C { + ... + $T $M(...) { + ... + $FACTORY.setFeature("http://xml.org/sax/features/external-general-entities", false); + ... + $FACTORY.setFeature("http://xml.org/sax/features/external-parameter-entities", false); + ... + } + ... + } + - pattern-inside: > + class $C { + ... + $T $M(...) { + ... + $FACTORY.setFeature("http://xml.org/sax/features/external-parameter-entities", false); + ... + $FACTORY.setFeature("http://xml.org/sax/features/external-general-entities",false); + ... + } + ... + } + - pattern: $M($X) + - focus-metavariable: $X +- id: java_xxe_rule-ExternalGeneralEntitiesTrue + severity: "WARNING" + languages: + - "java" + metadata: + cwe: "CWE-611" + shortDescription: "Improper restriction of XML external entity reference" + owasp: + - "A4:2017-XML External Entities (XXE)" + - "A05:2021-Security Misconfiguration" + security-severity: "MEDIUM" + references: + - "https://semgrep.dev/blog/2022/xml-security-in-java" + - "https://semgrep.dev/docs/cheat-sheets/java-xxe/" + - "https://blog.sonarsource.com/secure-xml-processor" + category: "security" + technology: + - "java" + - "xml" + cwe2022-top25: "true" + cwe2021-top25: "true" + license: "Commons Clause License Condition v1.0[LGPL-2.1-only]" + vulnerability_class: + - "XML Injection" + message: | + This rule identifies instances in the code where an XML parser is + configured to allow external general entities. Allowing the processing + of external general entities without proper validation or restriction + can lead to XXE attacks. An attacker can craft an XML document to + reference sensitive files on the server or external systems under the + attacker's control, leading to data disclosure, denial of service, or + server-side request forgery (SSRF). + + To mitigate this vulnerability, the application should be configured to + disable the use of external general entities in XML parsing. This can be + achieved by setting the feature + "http://xml.org/sax/features/external-general-entities" to false. + + Secure Code Example: + ``` + class GoodSAXBuilder { + public void GoodSAXBuilder1() throws ParserConfigurationException { + SAXBuilder saxBuilder = new SAXBuilder(); + saxBuilder.setFeature("http://xml.org/sax/features/external-general-entities", false); + } + } + ``` + pattern: | + $PARSER.setFeature("http://xml.org/sax/features/external-general-entities", + true); +- id: java_xxe_rule-ExternalParameterEntitiesTrue + severity: "WARNING" + languages: + - "java" + metadata: + cwe: "CWE-611" + shortDescription: "Improper restriction of XML external entity reference" + owasp: + - "A4:2017-XML External Entities (XXE)" + - "A05:2021-Security Misconfiguration" + security-severity: "MEDIUM" + references: + - "https://semgrep.dev/blog/2022/xml-security-in-java" + - "https://semgrep.dev/docs/cheat-sheets/java-xxe/" + - "https://blog.sonarsource.com/secure-xml-processor" + category: "security" + technology: + - "java" + - "xml" + cwe2022-top25: "true" + cwe2021-top25: "true" + license: "Commons Clause License Condition v1.0[LGPL-2.1-only]" + vulnerability_class: + - "XML Injection" + message: | + This rule identifies instances in the code where the XML parser is + configured to allow external parameter entities. Enabling external + entities in XML parsing can lead to XML External Entity (XXE) attacks, + where an attacker could exploit the XML parser to read sensitive files + from the server, perform denial of service (DoS) attacks, or achieve + server-side request forgery (SSRF). This vulnerability occurs when the + application processes XML input that includes external entity references + within an XML document. + + To mitigate this vulnerability, the application should be configured to disable + the use of external entities in XML parsing. This can be achieved by setting the + feature "http://xml.org/sax/features/external-parameter-entities" to false. + + Secure Code Example: + ``` + try { + DBFactory dbFactory = DocumentBuilderFactory.newInstance(); + // Disable external entities to mitigate XXE vulnerability + dbFactory.setFeature("http://xml.org/sax/features/external-parameter-entities", false); + dbFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + // Additional configuration for secure parsing + dbFactory.setFeature("http://xml.org/sax/features/external-general-entities", false); + dbFactory.setXIncludeAware(false); + dbFactory.setExpandEntityReferences(false); + + // Use the configured factory to create a document builder + DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); + // Parse an XML file using the secure document builder + Document doc = dBuilder.parse(new InputSource(new StringReader(xmlData))); + // Process the document as needed + } catch (ParserConfigurationException | SAXException | IOException e) { + // Handle exceptions appropriately + } + ``` + pattern: | + $PARSER.setFeature("http://xml.org/sax/features/external-parameter-entities", + true); +- id: java_xxe_rule-SAXParserFactoryDisallowDoctypeDeclMissing + severity: "WARNING" + languages: + - "java" + metadata: + cwe: "CWE-611" + shortDescription: "Improper restriction of XML external entity reference" + owasp: + - "A4:2017-XML External Entities (XXE)" + - "A05:2021-Security Misconfiguration" + security-severity: "MEDIUM" + references: + - "https://semgrep.dev/blog/2022/xml-security-in-java" + - "https://semgrep.dev/docs/cheat-sheets/java-xxe/" + - "https://blog.sonarsource.com/secure-xml-processor" + - "https://xerces.apache.org/xerces2-j/features.html" + category: "security" + technology: + - "java" + - "xml" + cwe2022-top25: "true" + cwe2021-top25: "true" + license: "Commons Clause License Condition v1.0[LGPL-2.1-only]" + vulnerability_class: + - "XML Injection" + message: | + DOCTYPE declarations are enabled for this SAXParserFactory. Enabling DOCTYPE + declarations without proper restrictions can make your application vulnerable to + XML External Entity (XXE) attacks. + In an XXE attack, an attacker can exploit the processing of external entity + references within an XML document to access internal files, conduct + denial-of-service attacks, or SSRF (Server Side Request Forgery), potentially + leading to sensitive information disclosure or system compromise. + + To mitigate this vulnerability, disable DOCTYPE declarations by setting the + feature `http://apache.org/xml/features/disallow-doctype-decl` to true. + Alternatively, allow DOCTYPE declarations and only prohibit external + entities declarations. This can be done by setting the features + `http://xml.org/sax/features/external-general-entities` and + `http://xml.org/sax/features/external-parameter-entities` to false. + NOTE: The previous links are not meant to be clicked. They are the literal + config key values that are supposed to be used to disable these features. + + Secure Code Example (You can do either of the following): + ``` + public void GoodSAXParserFactory() throws ParserConfigurationException { + SAXParserFactory spf = SAXParserFactory.newInstance(); + spf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + spf.newSAXParser(); + } + + public void GoodSAXParserFactory2() throws ParserConfigurationException { + SAXParserFactory spf = SAXParserFactory.newInstance(); + spf.setFeature("http://xml.org/sax/features/external-parameter-entities", false); + spf.setFeature("http://xml.org/sax/features/external-general-entities", false); + spf.newSAXParser(); + } + ``` + For more information, see + https://semgrep.dev/docs/cheat-sheets/java-xxe/#3a-documentbuilderfactory. + mode: taint + pattern-sources: + - by-side-effect: true + patterns: + - pattern-either: + - pattern: | + $FACTORY = SAXParserFactory.newInstance(); + - patterns: + - pattern: $FACTORY + - pattern-inside: | + class $C { + ... + $V $FACTORY = SAXParserFactory.newInstance(); + ... + } + - pattern-not-inside: > + class $C { + ... + $V $FACTORY = SAXParserFactory.newInstance(); + static { + ... + $FACTORY.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + ... + } + ... + } + - pattern-not-inside: > + class $C { + ... + $V $FACTORY = SAXParserFactory.newInstance(); + static { + ... + $FACTORY.setFeature("http://xml.org/sax/features/external-parameter-entities", false); + ... + $FACTORY.setFeature("http://xml.org/sax/features/external-general-entities", false); + ... + } + ... + } + - pattern-not-inside: > + class $C { + ... + $V $FACTORY = SAXParserFactory.newInstance(); + static { + ... + $FACTORY.setFeature("http://xml.org/sax/features/external-general-entities", false); + ... + $FACTORY.setFeature("http://xml.org/sax/features/external-parameter-entities", false); + ... + } + ... + } + pattern-sinks: + - patterns: + - pattern: $FACTORY.newSAXParser(); + pattern-sanitizers: + - by-side-effect: true + pattern-either: + - patterns: + - pattern-either: + - pattern: > + $FACTORY.setFeature("http://apache.org/xml/features/disallow-doctype-decl", + true); + - pattern: > + $FACTORY.setFeature("http://xml.org/sax/features/external-general-entities", + false); + + ... + + $FACTORY.setFeature("http://xml.org/sax/features/external-parameter-entities", false); + - pattern: > + $FACTORY.setFeature("http://xml.org/sax/features/external-parameter-entities", + false); + + ... + + $FACTORY.setFeature("http://xml.org/sax/features/external-general-entities", false); + - focus-metavariable: $FACTORY + - patterns: + - pattern-either: + - pattern-inside: > + class $C { + ... + $T $M(...) { + ... + $FACTORY.setFeature("http://apache.org/xml/features/disallow-doctype-decl", + true); + ... + } + ... + } + - pattern-inside: > + class $C { + ... + $T $M(...) { + ... + $FACTORY.setFeature("http://xml.org/sax/features/external-general-entities", false); + ... + $FACTORY.setFeature("http://xml.org/sax/features/external-parameter-entities", false); + ... + } + ... + } + - pattern-inside: > + class $C { + ... + $T $M(...) { + ... + $FACTORY.setFeature("http://xml.org/sax/features/external-parameter-entities", false); + ... + $FACTORY.setFeature("http://xml.org/sax/features/external-general-entities",false); + ... + } + ... + } + - pattern: $M($X) + - focus-metavariable: $X +- id: java_xxe_rule-TransformerfactoryDTDNotDisabled + severity: "WARNING" + languages: + - "java" + metadata: + cwe: "CWE-611" + shortDescription: "Improper restriction of XML external entity reference" + owasp: + - "A4:2017-XML External Entities (XXE)" + - "A05:2021-Security Misconfiguration" + security-severity: "MEDIUM" + references: + - "https://semgrep.dev/blog/2022/xml-security-in-java" + - "https://semgrep.dev/docs/cheat-sheets/java-xxe/" + - "https://blog.sonarsource.com/secure-xml-processor" + - "https://xerces.apache.org/xerces2-j/features.html" + category: "security" + technology: + - "java" + - "xml" + license: "Commons Clause License Condition v1.0[LGPL-2.1-only]" + message: | + This rule identifies configurations of the TransformerFactory class where + DOCTYPE declarations are enabled. Enabling DOCTYPE declarations without + proper restrictions can make your application vulnerable to XML External + Entity (XXE) attacks. In an XXE attack, an attacker can exploit the + processing of external entity references within an XML document to access + internal files, conduct denial-of-service attacks, or SSRF (Server Side + Request Forgery), potentially leading to sensitive information disclosure + or system compromise. + + To mitigate XXE vulnerabilities related to the TransformerFactory instance in + Java, it is crucial to disable external DTD (Document Type Definition) and + external stylesheet processing. This can be accomplished by setting the + ACCESS_EXTERNAL_DTD and ACCESS_EXTERNAL_STYLESHEET factory attributes to an + empty string (""). This approach prevents the parser from fetching and processing + external references specified in the XML document. + + Secure Code Example: + ``` + public static void configureTransformerFactory() throws TransformerConfigurationException { + TransformerFactory factory = TransformerFactory.newInstance(); + // Disable access to external DTDs and stylesheets to prevent XXE + factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, ""); + factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, ""); + } + ``` + mode: taint + pattern-sources: + - by-side-effect: true + # https://gitlab.com/gitlab-org/security-products/sast-rules/-/merge_requests/466#note_1821811133 + patterns: + - pattern-either: + - pattern: | + $FACTORY = javax.xml.transform.TransformerFactory.newInstance(); + - patterns: + - pattern: $FACTORY + - pattern-inside: | + class $C { + ... + $V $FACTORY = javax.xml.transform.TransformerFactory.newInstance(); + ... + } + - pattern-not-inside: > + class $C { + ... + $V $FACTORY = javax.xml.transform.TransformerFactory.newInstance(); + static { + ... + $FACTORY.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, ""); + ... + $FACTORY.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, ""); + ... + } + ... + } + - pattern-not-inside: > + class $C { + ... + $V $FACTORY = javax.xml.transform.TransformerFactory.newInstance(); + static { + ... + $FACTORY.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, ""); + ... + $FACTORY.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, ""); + ... + } + ... + } + - pattern-not-inside: > + class $C { + ... + $V $FACTORY = javax.xml.transform.TransformerFactory.newInstance(); + static { + ... + $FACTORY.setAttribute("=~/.*accessExternalDTD.*/", ""); + ... + $FACTORY.setAttribute("=~/.*accessExternalStylesheet.*/", ""); + ... + } + ... + } + - pattern-not-inside: > + class $C { + ... + $V $FACTORY = javax.xml.transform.TransformerFactory.newInstance(); + static { + ... + $FACTORY.setAttribute("=~/.*accessExternalStylesheet.*/", ""); + ... + $FACTORY.setAttribute("=~/.*accessExternalDTD.*/", ""); + ... + } + ... + } + pattern-sinks: + - patterns: + - pattern: $FACTORY.newTransformer(...); + pattern-sanitizers: + - by-side-effect: true + pattern-either: + - patterns: + - pattern-either: + - pattern: > + $FACTORY.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, + ""); ... + + $FACTORY.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, ""); + - pattern: > + $FACTORY.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, + ""); + + ... + + $FACTORY.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, ""); + - pattern: > + $FACTORY.setAttribute("=~/.*accessExternalStylesheet.*/", + ""); ... + + $FACTORY.setAttribute("=~/.*accessExternalDTD.*/", ""); + - pattern: > + $FACTORY.setAttribute("=~/.*accessExternalDTD.*/", ""); + + ... + + $FACTORY.setAttribute("=~/.*accessExternalStylesheet.*/", ""); + - focus-metavariable: $FACTORY + - patterns: + - pattern-either: + - pattern-inside: > + class $C { + ... + $T $M(...) { + ... + $FACTORY.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, ""); + ... + $FACTORY.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, ""); + ... + } + ... + } + - pattern-inside: > + class $C { + ... + $T $M(...) { + ... + $FACTORY.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, ""); + ... + $FACTORY.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, ""); + ... + } + ... + } + - pattern-inside: > + class $C { + ... + $T $M(...) { + ... + $FACTORY.setAttribute("=~/.*accessExternalStylesheet.*/", ""); + ... + $FACTORY.setAttribute("=~/.*accessExternalDTD.*/", ""); + ... + } + ... + } + - pattern-inside: > + class $C { + ... + $T $M(...) { + ... + $FACTORY.setAttribute("=~/.*accessExternalDTD.*/", ""); + ... + $FACTORY.setAttribute("=~/.*accessExternalStylesheet.*/", ""); + ... + } + ... + } + - pattern: $M($X) + - focus-metavariable: $X +- id: java_xxe_rule-XMLInputFactoryExternalEntitiesEnabled + severity: "WARNING" + languages: + - "java" + metadata: + cwe: "CWE-611" + shortDescription: "Improper restriction of XML external entity reference" + owasp: + - "A4:2017-XML External Entities (XXE)" + - "A05:2021-Security Misconfiguration" + security-severity: "MEDIUM" + references: + - "https://semgrep.dev/blog/2022/xml-security-in-java" + - "https://semgrep.dev/docs/cheat-sheets/java-xxe/" + - "https://www.blackhat.com/docs/us-15/materials/us-15-Wang-FileCry-The-New-Age-Of-XXE-java-wp.pdf" + category: "security" + cwe2022-top25: "true" + cwe2021-top25: "true" + likelihood: "LOW" + impact: "HIGH" + confidence: "LOW" + license: "Commons Clause License Condition v1.0[LGPL-2.1-only]" + vulnerability_class: + - "XML Injection" + message: | + XML external entities are enabled for this XMLInputFactory. Enabling external + entities can make the application vulnerable to XML external entity attacks. + In an XXE attack, an attacker can exploit the processing of external entity + references within an XML document to access internal files, conduct + denial-of-service attacks, or SSRF (Server Side Request Forgery), potentially + leading to sensitive information disclosure or system compromise. + + To mitigate this vulnerability, disable external entities by + setting "javax.xml.stream.isSupportingExternalEntities" to false. + + Secure Code Example: + ``` + public GoodXMLInputFactory() { + final XMLInputFactory xmlInputFactory = XMLInputFactory.newFactory(); + xmlInputFactory.setProperty(XMLInputFactory.SUPPORT_DTD, false); + xmlInputFactory.setProperty("javax.xml.stream.isSupportingExternalEntities", false); + } + ``` + For more details, refer to https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.md#xmlinputfactory-a-stax-parser + pattern: | + $XMLFACTORY.setProperty("javax.xml.stream.isSupportingExternalEntities", + true); + +- id: java_xxe_rule-XMLStreamRdr + languages: + - "java" + message: | + External XML entities are a feature of XML parsers that allow + documents to contain references to other documents or data. This + feature can be abused to read files, communicate with external + hosts, exfiltrate data, or cause a Denial of Service (DoS). + In most XML parsers, the recommendation to protect against XXE is + to disable the doctype feature. + Unfortunately use of the `XMLInputFactory` requires that the doctypes + feature be enabled. Instead the application can set the `ACCESS_EXTERNAL_DTD` + to an empty string and disable `javax.xml.stream.isSupportingExternalEntities`. + + Secure Code Example: + ``` + // Create an XMLInputFactory + XMLInputFactory factory = XMLInputFactory.newFactory(); + // Set the ACCESS_EXTERNAL_DTD property to an empty string so it won't access + // entities using protocols + // (ref: + https://docs.oracle.com/javase/8/docs/api/javax/xml/XMLConstants.html#ACCESS_EXTERNAL_DTD) + factory.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, ""); + // Additionally, disable support for resolving external entities + factory.setProperty("javax.xml.stream.isSupportingExternalEntities", false); + // Continue to work with the factory/stream parser + ``` + + For more information on XML security see OWASP's guide: + https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#java + patterns: + - pattern-not-inside: | + (javax.xml.stream.XMLInputFactory $FAC).setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, ""); + ... + - pattern-not-inside: + patterns: + - pattern-either: + - pattern: | + (javax.xml.stream.XMLInputFactory $FAC).setProperty(XMLInputFactory.SUPPORT_DTD, $FALSE); + ... + - pattern: | + (javax.xml.stream.XMLInputFactory $FAC).setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, $FALSE); + ... + - pattern: | + (javax.xml.stream.XMLInputFactory $FAC).setProperty("javax.xml.stream.isSupportingExternalEntities", $FALSE); + ... + - metavariable-pattern: + metavariable: $FALSE + pattern-either: + - pattern: | + false + - pattern: | + Boolean.FALSE + - pattern: | + (javax.xml.stream.XMLInputFactory $FAC).createXMLStreamReader(...) + metadata: + shortDescription: "Improper restriction of XML external entity reference ('XXE')" + category: "security" + cwe: "CWE-611" + owasp: + - "A4:2017-XML External Entities (XXE)" + - "A05:2021-Security Misconfiguration" + security-severity: "MEDIUM" + severity: "WARNING" +- id: javascript_exec_rule-child-process + message: | + OS command injection is a critical vulnerability that can lead to a full system + compromise as it may allow an adversary to pass in arbitrary commands or arguments + to be executed. + + User input should never be used in constructing commands or command arguments + to functions which execute OS commands. This includes filenames supplied by + user uploads or downloads. + + Ensure your application does not: + + - Use user-supplied information in the process name to execute. + - Use user-supplied information in an OS command execution function which does + not escape shell meta-characters. + - Use user-supplied information in arguments to OS commands. + + The application should have a hardcoded set of arguments that are to be passed + to OS commands. If filenames are being passed to these functions, it is + recommended that a hash of the filename be used instead, or some other unique + identifier. It is strongly recommended that a native library that implements + the same functionality be used instead of using OS system commands, due to the + risk of unknown attacks against third-party commands. + + When specifying the OS command, ensure the application uses the full path + information, otherwise the OS may attempt to look up which process to execute + and could be vulnerable to untrusted search path vulnerabilities (CWE-426). + + Example of safely executing an OS command: + ``` + const child_process = require('child_process'); + const fs = require('fs'); + const crypto = require('node:crypto'); + const { mkdtempSync } = require('node:fs'); + + function executeCommand(userFileData) { + // Create a temporary directory, preferably in an application directory + // that only the application has access to. + const fileDir = mkdtempSync('/tmp/tmpdir-'); + // Generate a random filename, do not use user input + const filePath = fileDir + path.sep + crypto.randomUUID(); + // Write the user-supplied data to the temporary file. + fs.writeFileSync(filePath, userFileData); + // Execute a program with a hardcoded path to the binary + child_process.exec(`/bin/cat ${filePath}`, (error, stdout, stderr) => { + // Delete the temporary directory and file if no longer needed + fs.rmSync(fileDir, { recursive: true, force: true }); + if (error) { + console.error(`exec error: ${error}`); + return; + } + console.log(`stdout: ${stdout}`); + console.error(`stderr: ${stderr}`); + }); + } + ``` + + For more information on OS command injection, see OWASP's guide: + https://cheatsheetseries.owasp.org/cheatsheets/OS_Command_Injection_Defense_Cheat_Sheet.html + + Detected non-literal calls to child_process.exec(). This could lead to a command + injection vulnerability. + metadata: + cwe: "CWE-78" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + shortDescription: "Improper neutralization of special elements used in an OS command ('OS Command Injection')" + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Nodejs_Security_Cheat_Sheet.html#do-not-use-dangerous-functions + source-rule-url: https://github.com/nodesecurity/eslint-plugin-security/blob/master/rules/detect-child-process.js + category: "security" + technology: + - javascript + license: Commons Clause License Condition v1.0[LGPL-2.1-only] + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + vulnerability_class: + - Command Injection + security-severity: "HIGH" + languages: + - javascript + - typescript + severity: "ERROR" + options: + taint_unify_mvars: true + mode: taint + pattern-sources: + - patterns: + - pattern-inside: | + function ... (...,$ARG,...) { + ... + } + - focus-metavariable: $ARG + pattern-sinks: + - patterns: + - pattern-either: + - pattern-inside: | + $CP = require('child_process') + ... + - pattern-inside: | + import * as $CP from 'child_process' + ... + - pattern-inside: | + import $CP from 'child_process' + ... + - pattern-either: + - pattern: $CP.exec($CMD,...) + - pattern: $CP.execSync($CMD,...) + - pattern: $CP.spawn($CMD,...) + - pattern: $CP.spawnSync($CMD,...) + - focus-metavariable: $CMD + pattern-sanitizers: + - pattern: | + $CMD = "..." + - pattern: | + $CMD = ["...",...] +- id: php_assert_rule-assert-use + mode: taint + pattern-sources: + - pattern-either: + - patterns: + - pattern-either: + - pattern: $_GET + - pattern: $_POST + - pattern: $_COOKIE + - pattern: $_REQUEST + - pattern: $_SERVER + - patterns: + - pattern: | + Route::$METHOD($ROUTENAME, function(..., $ARG, ...) { ... }) + - focus-metavariable: $ARG + pattern-sinks: + - patterns: + - pattern: assert($SINK, ...); + - pattern-not: assert("...", ...); + - pattern: $SINK + message: Calling assert with user input is equivalent to eval'ing. + metadata: + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + cwe: "CWE-95" + shortDescription: "Improper neutralization of directives in dynamically evaluated code ('Eval Injection')" + references: + - https://www.php.net/manual/en/function.assert + - https://github.com/FloeDesignTechnologies/phpcs-security-audit/blob/master/Security/Sniffs/BadFunctions/AssertsSniff.php + category: security + technology: + - php + subcategory: + - vuln + license: Commons Clause License Condition v1.0[LGPL-2.1-only] + vulnerability_class: + - Code Injection + security-severity: "CRITICAL" + languages: + - php + severity: ERROR +- id: php_backticks_rule-backticks-use + pattern: "`...`;" + message: Backticks use may lead to command injection vulnerabilities. + metadata: + cwe: "CWE-94" + shortDescription: "Improper control of generation of code ('Code Injection')" + references: + - https://www.php.net/manual/en/language.operators.execution.php + - https://github.com/FloeDesignTechnologies/phpcs-security-audit/blob/master/Security/Sniffs/BadFunctions/BackticksSniff.php + category: security + technology: + - php + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + cwe2022-top25: true + subcategory: + - audit + license: Commons Clause License Condition v1.0[LGPL-2.1-only] + vulnerability_class: + - Code Injection + security-severity: "CRITICAL" + languages: + - php + severity: ERROR +- id: php_crypto_rule-weak-crypto + patterns: + - pattern: $FUNC(...); + - metavariable-regex: + metavariable: $FUNC + regex: crypt|md5|md5_file|sha1|sha1_file|str_rot13 + message: Detected usage of weak crypto function. Consider using stronger + alternatives. + metadata: + cwe: "CWE-328" + shortDescription: "Use of weak hash" + references: + - https://www.php.net/manual/en/book.sodium.php + - https://github.com/FloeDesignTechnologies/phpcs-security-audit/blob/master/Security/Sniffs/BadFunctions/CryptoFunctionsSniff.php + category: security + technology: + - php + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + subcategory: + - audit + license: Commons Clause License Condition v1.0[LGPL-2.1-only] + vulnerability_class: + - Insecure Hashing Algorithm + security-severity: "MEDIUM" + languages: + - php + severity: WARNING +- id: php_eval_rule-eval-use + patterns: + - pattern: eval(...); + - pattern-not: eval('...'); + message: Evaluating non-constant commands. This can lead to command injection. + metadata: + cwe: "CWE-78" + shortDescription: "Improper neutralization of special elements used in an OS command ('OS Command Injection')" + references: + - https://www.php.net/manual/en/function.eval + - https://github.com/FloeDesignTechnologies/phpcs-security-audit/blob/master/Security/Sniffs/BadFunctions/NoEvalsSniff.php + category: security + technology: + - php + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + license: Commons Clause License Condition v1.0[LGPL-2.1-only] + vulnerability_class: + - Command Injection + security-severity: "CRITICAL" + languages: + - php + severity: ERROR +- id: php_exec_rule-exec-use + patterns: + - pattern: $FUNC(...); + - pattern-not: $FUNC('...', ...); + - metavariable-regex: + metavariable: $FUNC + regex: exec|passthru|proc_open|popen|shell_exec|system|pcntl_exec + message: Executing non-constant commands. This can lead to command injection. + metadata: + cwe: "CWE-94" + shortDescription: "Improper control of generation of code ('Code Injection')" + references: + - https://github.com/FloeDesignTechnologies/phpcs-security-audit/blob/master/Security/Sniffs/BadFunctions/SystemExecFunctionsSniff.php + category: security + technology: + - php + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + cwe2022-top25: true + subcategory: + - audit + license: Commons Clause License Condition v1.0[LGPL-2.1-only] + vulnerability_class: + - Code Injection + security-severity: "CRITICAL" + languages: + - php + severity: ERROR +- id: php_file_rule-file-inclusion + message: Detected non-constant file inclusion. This can lead to local file + inclusion (LFI) or remote file inclusion (RFI) if user input reaches this + statement. LFI and RFI could lead to sensitive files being obtained by + attackers. Instead, explicitly specify what to include. If that is not a + viable solution, validate user input thoroughly. + metadata: + cwe: "CWE-98" + shortDescription: "Improper control of filename for include/require statement in PHP program ('PHP Remote File Inclusion')" + references: + - https://www.php.net/manual/en/function.include.php + - https://github.com/FloeDesignTechnologies/phpcs-security-audit/blob/master/Security/Sniffs/BadFunctions/EasyRFISniff.php + - https://en.wikipedia.org/wiki/File_inclusion_vulnerability#Types_of_Inclusion + category: security + technology: + - php + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + subcategory: + - audit + license: Commons Clause License Condition v1.0[LGPL-2.1-only] + vulnerability_class: + - Code Injection + security-severity: "CRITICAL" + languages: + - php + severity: ERROR + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - pattern: $_GET + - pattern: $_POST + - pattern: $_COOKIE + - pattern: $_REQUEST + - pattern: $_SERVER + pattern-sanitizers: + - patterns: + - pattern-either: + - pattern-inside: basename($PATH, ...) + - pattern-inside: linkinfo($PATH, ...) + - pattern-inside: readlink($PATH, ...) + - pattern-inside: realpath($PATH, ...) + - pattern-inside: include_safe(...) + pattern-sinks: + - patterns: + - pattern-inside: $FUNC(...); + - pattern: $VAR + - metavariable-regex: + metavariable: $FUNC + regex: \b(include|include_once|require|require_once)\b +- id: php_ftp_rule-ftp-use + patterns: + - pattern: $FUNC(...); + - metavariable-regex: + metavariable: $FUNC + regex: ftp_.+ + message: FTP allows for unencrypted file transfers. Consider using an encrypted + alternative. + metadata: + cwe: "CWE-319" + shortDescription: "Cleartext transmission of sensitive information" + references: + - https://www.php.net/manual/en/intro.ftp.php + - https://github.com/FloeDesignTechnologies/phpcs-security-audit/blob/master/Security/Sniffs/BadFunctions/FringeFunctionsSniff.php + category: security + technology: + - php + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + subcategory: + - audit + license: Commons Clause License Condition v1.0[LGPL-2.1-only] + vulnerability_class: + - Mishandled Sensitive Information + security-severity: "MEDIUM" + languages: + - php + severity: WARNING +- id: php_mcrypt_rule-mcrypt-use + patterns: + - pattern: $FUNC(...); + - metavariable-regex: + metavariable: $FUNC + regex: (mcrypt_|mdecrypt_).+ + message: Mcrypt functionality has been deprecated and/or removed in recent PHP + versions. Consider using Sodium or OpenSSL. + metadata: + cwe: "CWE-676" + shortDescription: "Use of potentially dangerous function" + references: + - https://www.php.net/manual/en/intro.mcrypt.php + - https://github.com/FloeDesignTechnologies/phpcs-security-audit/blob/master/Security/Sniffs/BadFunctions/CryptoFunctionsSniff.php + category: security + owasp: + - "A9:2017-Using Components with Known Vulnerabilities" + - "A06:2021-Vulnerable and Outdated Components" + technology: + - php + subcategory: + - audit + license: Commons Clause License Condition v1.0[LGPL-2.1-only] + vulnerability_class: + - Dangerous Method or Function + security-severity: "MEDIUM" + languages: + - php + severity: WARNING +- id: php_phpinfo_rule-phpinfo-use + pattern: phpinfo(...); + message: The 'phpinfo' function may reveal sensitive information about your + environment. + metadata: + cwe: "CWE-497" + shortDescription: "Exposure of sensitive system information to an unauthorized control sphere" + references: + - https://www.php.net/manual/en/function.phpinfo + - https://github.com/FloeDesignTechnologies/phpcs-security-audit/blob/master/Security/Sniffs/BadFunctions/PhpinfosSniff.php + category: security + technology: + - php + owasp: + - "A5:2017-Broken Access Control" + - "A01:2021-Broken Access Control" + cwe2021-top25: true + subcategory: + - vuln + license: Commons Clause License Condition v1.0[LGPL-2.1-only] + vulnerability_class: + - Mishandled Sensitive Information + security-severity: "MEDIUM" + languages: + - php + severity: WARNING +- id: properties_spring_rule-SpringActuatorFullyEnabled + languages: + - "generic" + severity: "WARNING" + message: | + Spring Boot Actuator is fully enabled. This exposes sensitive endpoints + such as /actuator/env, /actuator/logfile, /actuator/heapdump and others. + If the application lacks proper security measures (e.g., authentication and + authorization), sensitive data could be accessed, compromising the application and + its infrastructure. This configuration poses a serious risk in production + environments or public-facing deployments. + + To mitigate the risks, take the following measures: + - Expose only the Actuator endpoints required for your use case + - For production environments, restrict exposure to non-sensitive endpoints + like `health` or `info` + - Ensure Actuator endpoints are protected with authentication and authorization + (e.g., via Spring Security) + - Use environment-specific configurations to limit exposure in production + + Secure Code Example: + Instead of include: "*", list only the endpoints you need to expose: + ``` + management.endpoints.web.exposure.include="health,info,metrics" + ``` + + References: + - https://docs.spring.io/spring-boot/reference/actuator/endpoints.html#actuator.endpoints.exposing + - https://medium.com/walmartglobaltech/perils-of-spring-boot-actuators-misconfiguration-185c43a0f785 + - https://blog.maass.xyz/spring-actuator-security-part-1-stealing-secrets-using-spring-actuators + metadata: + likelihood: MEDIUM + impact: HIGH + confidence: MEDIUM + shortDescription: "Exposure of sensitive system information to an unauthorized control sphere" + category: "security" + cwe: "CWE-497" + owasp: + - "A01:2021-Broken Access Control" + - "A3:2017-Sensitive Data Exposure" + security-severity: "Medium" + technology: + - "java" + paths: + include: + - "*properties" + pattern: management.endpoints.web.exposure.include=* +- id: python_crypto_rule-HTTPConnectionPool + languages: + - python + pattern-either: + - pattern: urllib3.HTTPConnectionPool(...) + - pattern: urllib3.connectionpool.HTTPConnectionPool(...) + message: | + The application is using HTTPConnectionPool method. This method transmits + data in cleartext, which is vulnerable to MITM (Man in the middle) + attacks. In MITM attacks, the data transmitted over the unencrypted + connection can be intercepted, read and/or modified by unauthorized + parties which can lead to data integrity and confidentiality loss. + + To mitigate this issue, use HTTPSConnectionPool instead, which encrypts + communications and enhances security. + + Secure Code Example: + ``` + import urllib3 + spool = urllib3.connectionpool.HTTPSConnectionPool("example.com") + ``` + metadata: + category: "security" + cwe: "CWE-319" + shortDescription: "Cleartext transmission of sensitive information" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + security-severity: "MEDIUM" + references: + - "https://urllib3.readthedocs.io/en/1.2.1/pools.html#urllib3.connectionpool.HTTPSConnectionPool" + technology: + - "python" + subcategory: + - "audit" + likelihood: "MEDIUM" + impact: "MEDIUM" + confidence: "MEDIUM" + severity: "WARNING" +- id: python_django_rule-django-raw-used + message: | + SQL Injections are a critical type of vulnerability that can lead to data + or system compromise. By dynamically generating SQL query strings, user + input may be able to influence the logic of the SQL statement. + This could lead to an adversary accessing information they should not + have access to, or in some circumstances, being able to execute OS functionality + or code. + + Replace all dynamically generated SQL queries with parameterized queries. + In situations where dynamic queries must be created, never use direct user input, + but instead use a map or dictionary of valid values and resolve them using a user + supplied key. + + For example, some database drivers do not allow parameterized queries for + `>` or `<` comparison operators. In these cases, do not use a user supplied + `>` or `<` value, but rather have the user supply a `gt` or `lt` value. + The alphabetical values are then used to look up the `>` and `<` values to be used + in the construction of the dynamic query. The same goes for other queries where + column or table names are required but cannot be parameterized. + + Data that is possible user-controlled from a python request is passed + to `raw()` function. To remediate this issue, use django's QuerySets, + which are built with query parameterization and therefore not vulnerable + to sql injection. For example, you could use `Entry.objects.filter(date=2006)` + + If for some reason this is not feasible, ensure calls including user-supplied + data pass it in to the `params` parameter of the `raw()` method. + Below is an example using `raw()`, passing in user-supplied data as `params`. + This will treat the query as a parameterized query and `params` as strictly data, + preventing any possibility of SQL Injection. + + ``` + def test(request): + uname = request.GET["username"] + res = User.objects.raw('SELECT * FROM myapp_user WHERE username = %s', (uname,)) + ``` + + For more information on QuerySet see: + - https://docs.djangoproject.com/en/5.0/ref/models/querysets/ + + For more information on SQL Injection see OWASP: + - https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html + + metadata: + cwe: "CWE-89" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + category: "security" + shortDescription: "Improper neutralization of special elements used in an SQL Command ('SQL Injection')" + security-severity: High + languages: + - python + severity: ERROR + mode: taint + pattern-sources: + - patterns: + - pattern: $PARAM + - pattern-inside: | + def $VIEW(...,$PARAM,...): + ... + return ... + pattern-sinks: + - patterns: + - pattern: $QUERY + - pattern-inside: $MODEL.objects.raw($QUERY, ... ) + + + +- id: python_django_rule-django-rawsql-used + languages: + - "python" + message: | + SQL Injections are a critical type of vulnerability that can lead to data or system compromise. By + dynamically generating SQL query strings, user input may be able to influence the logic of the SQL + statement. This could lead to an adversary accessing information they should not have access to, or in + some circumstances, being able to execute OS functionality or code. + + Replace all dynamically generated SQL queries with parameterized queries. In situations where dynamic + queries must be created, never use direct user input, but instead use a map or dictionary of valid values + and resolve them using a user supplied key. + + For example, some database drivers do not allow parameterized queries for `>` or `<` comparison operators. + In these cases, do not use a user supplied `>` or `<` value, but rather have the user supply a `gt` or `lt` + value. The alphabetical values are then used to look up the `>` and `<` values to be used in the + construction of the dynamic query. The same goes for other queries where column or table names are required + but cannot be parameterized. + + To remediate this issue, do not use `raw` or `RawSQL` but use other `QuerySet` methods to achieve the same + goals. If for some reason this is not feasible, ensure calls including user-supplied data pass it in to + the `params` parameter of the `RawSQL` method. + + While not recommended due to [potential SQL Injection](https://docs.djangoproject.com/en/5.0/ref/models/expressions/#raw-sql-expressions), below is an example using `RawSQL`. + Passing in user-supplied data as a `param` which will escape the input: + + ``` + # If dealing with integer based user input, restrict the values to integers only using the + # path configuration: path('/someview/', views.some_view, name='someview'), + + # views.py + def some_view(request, user_supplied_id): + # Never use string interpolation in the `sql` parameter. + # Never quote the `%s` string format such as `... where id='%s'` as this could lead to SQL Injection. + # Pass the user supplied data only in the `params` parameter. + for obj in DBObject.objects.all().annotate( + val=RawSQL(sql="select id from some_secondary_table where id=%s", params=[user_supplied_id])): + # Work with the results from the query + # ... + ``` + + For more information on QuerySets see: + - https://docs.djangoproject.com/en/4.2/ref/models/querysets/#queryset-api + + For more information on SQL Injection see OWASP: + - https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html + metadata: + cwe: "CWE-89" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + category: "security" + shortDescription: "Improper neutralization of special elements used in an SQL Command ('SQL Injection')" + security-severity: "CRITICAL" + mode: "taint" + pattern-sources: + - patterns: + - pattern: $PARAM + - pattern-inside: | + def $VIEW(...,$PARAM,...): + ... + return ... + pattern-sinks: + - patterns: + - pattern: $QUERY + - pattern-inside: django.db.models.expressions.RawSQL($QUERY, ... ) + severity: ERROR +- id: python_escaping_rule-django + languages: + - "python" + message: | + Cross Site Scripting (XSS) is an attack which exploits a web application or system to treat + user input + as markup or script code. It is important to encode the data depending on the specific context + it + is used in. There are at least six context types: + + - Inside HTML tags `
context 1
` + - Inside attributes: `
` + - Inside event attributes `` + - Inside script blocks: `` + - Unsafe element HTML assignment: `element.innerHTML = "context 5"` + - Inside URLs: `link` + + Script blocks alone have multiple ways they need to be encoded. Extra care must be taken if + user input + is ever output inside of script tags. + + User input that is displayed within the application must be encoded, sanitized or validated + to ensure it cannot be treated as HTML or executed as Javascript code. Care must also be + taken + to not mix server-side templating with client-side templating, as the server-side templating + will + not encode things like {{ 7*7 }} which may execute client-side templating features. + + It is _NOT_ advised to encode user input prior to inserting into a data store. The data will + need to be + encoded depending on context of where it is output. It is much safer to force the displaying + system to + handle the encoding and not attempt to guess how it should be encoded. + + Consider using + [format_html](https://docs.djangoproject.com/en/4.2/ref/utils/#django.utils.html.format_html) + instead of + the `django.utils.safestring` methods. + + Example using `format_html`: + ``` + # Use format_html to create an HTML link, using href as the parameter + # which will be encoded automatically + format_html("
  • Some Link
  • ", href) + ``` + + For more information on XSS see OWASP: + - https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html + metadata: + cwe: "CWE-79" + owasp: + - "A7:2017-Cross-Site Scripting (XSS)" + - "A03:2021-Injection" + category: "security" + shortDescription: "Improper neutralization of input during web page generation + ('Cross-site Scripting')" + security-severity: "Medium" + patterns: + - pattern-not-inside: |- + django.utils.html.format_html(...) + - pattern-either: + - patterns: + - pattern: "django.utils.safestring.SafeText(...)" + - pattern-not: "django.utils.safestring.SafeText(\"...\")" + - patterns: + - pattern: "django.utils.safestring.SafeUnicode(...)" + - pattern-not: "django.utils.safestring.SafeUnicode(\"...\")" + - patterns: + - pattern: "django.utils.safestring.SafeString(...)" + - pattern-not: "django.utils.safestring.SafeString(\"...\")" + - patterns: + - pattern: "django.utils.safestring.SafeBytes(...)" + - pattern-not: "django.utils.safestring.SafeBytes(\"...\")" + - patterns: + - pattern: "django.utils.safestring.mark_safe(...)" + - pattern-not: "django.utils.safestring.mark_safe(\"...\")" + severity: "WARNING" +- id: python_flask_rule-path-traversal-open + languages: + - "python" + severity: "ERROR" + message: | + Found request data in a call to 'open'. An attacker can manipulate this input to access files outside the intended + directory. This can lead to unauthorized access to sensitive files or directories. To prevent path traversal attacks, + avoid using user-controlled input in file paths. If you must use user-controlled input, validate and sanitize the + input to ensure it does not contain any path traversal sequences. For example, you can use the `os.path.join` function + to safely construct file paths or validate that the absolute path starts with the directory which is whitelisted for + accessing file. The following code snippet demonstrates how to validate a file path from user-controlled input: + ``` + import os + + def safe_open_file(filename, base_path): + # Resolve the absolute path of the user-supplied filename + absolute_path = os.path.abspath(filename) + + # Check that the absolute path starts with the base path + if not absolute_path.startswith(base_path): + raise ValueError("Invalid file path") + + return open(absolute_path, 'r') + ``` + For more information, see the OWASP Path Traversal page: https://owasp.org/www-community/attacks/Path_Traversal + metadata: + cwe: "CWE-22" + shortDescription: "Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')" + owasp: + - "A5:2017-Broken Access Control" + - "A01:2021-Broken Access Control" + category: "security" + security-severity: "CRITICAL" + references: + - https://owasp.org/www-community/attacks/Path_Traversal + technology: + - "flask" + likelihood: "MEDIUM" + impact: "HIGH" + confidence: "MEDIUM" + pattern-either: + - patterns: + - pattern: open(...) + - pattern-either: + - pattern-inside: | + @$APP.route($ROUTE, ...) + def $FUNC(..., $ROUTEVAR, ...): + ... + open(..., <... $ROUTEVAR ...>, ...) + - pattern-inside: | + @$APP.route($ROUTE, ...) + def $FUNC(..., $ROUTEVAR, ...): + ... + with open(..., <... $ROUTEVAR ...>, ...) as $FD: + ... + - pattern-inside: | + @$APP.route($ROUTE, ...) + def $FUNC(..., $ROUTEVAR, ...): + ... + $INTERIM = <... $ROUTEVAR ...> + ... + open(..., <... $INTERIM ...>, ...) + - pattern: open(..., <... flask.request.$W.get(...) ...>, ...) + - pattern: open(..., <... flask.request.$W[...] ...>, ...) + - pattern: open(..., <... flask.request.$W(...) ...>, ...) + - pattern: open(..., <... flask.request.$W ...>, ...) + - patterns: + - pattern-inside: | + $INTERIM = <... flask.request.$W.get(...) ...> + ... + open(<... $INTERIM ...>, ...) + - pattern: open(...) + - patterns: + - pattern-inside: | + $INTERIM = <... flask.request.$W[...] ...> + ... + open(<... $INTERIM ...>, ...) + - pattern: open(...) + - patterns: + - pattern-inside: | + $INTERIM = <... flask.request.$W(...) ...> + ... + open(<... $INTERIM ...>, ...) + - pattern: open(...) + - patterns: + - pattern-inside: | + $INTERIM = <... flask.request.$W ...> + ... + open(<... $INTERIM ...>, ...) + - pattern: open(...) + - patterns: + - pattern-inside: | + $INTERIM = <... flask.request.$W.get(...) ...> + ... + with open(<... $INTERIM ...>, ...) as $F: + ... + - pattern: open(...) + - patterns: + - pattern-inside: | + $INTERIM = <... flask.request.$W[...] ...> + ... + with open(<... $INTERIM ...>, ...) as $F: + ... + - pattern: open(...) + - patterns: + - pattern-inside: | + $INTERIM = <... flask.request.$W(...) ...> + ... + with open(<... $INTERIM ...>, ...) as $F: + ... + - pattern: open(...) + - patterns: + - pattern-inside: | + $INTERIM = <... flask.request.$W ...> + ... + with open(<... $INTERIM ...>, ...) as $F: + ... + - pattern: open(...) +- id: python_flask_rule-tainted-sql-string + languages: + - python + message: | + Detected user input used to manually construct a SQL string. This is usually + bad practice because manual construction could accidentally result in a SQL + injection. An attacker could use a SQL injection to steal or modify contents + of the database. Instead, use a parameterized query which is available + by default in most database engines. Alternatively, consider using an + object-relational mapper (ORM) such as SQLAlchemy which will protect your queries. + + SQL Injections are a critical type of vulnerability that can lead to data + or system compromise. By dynamically generating SQL query strings, user + input may be able to influence the logic of an SQL statement. + This could lead to an malicious parties accessing information they should not + have access to, or in some circumstances, being able to execute OS functionality + or code. + + Replace all dynamically generated SQL queries with parameterized queries. + In situations where dynamic queries must be created, never use direct user input, + but instead use a map or dictionary of valid values and resolve them using a user + supplied key. + + For example, some database drivers do not allow parameterized queries for + `>` or `<` comparison operators. In these cases, do not use a user supplied + `>` or `<` value, but rather have the user supply a `gt` or `lt` value. + The alphabetical values are then used to look up the `>` and `<` values to be used + in the construction of the dynamic query. The same goes for other queries where + column or table names are required but cannot be parameterized. + Data that is possible user-controlled from a python request is passed + to `execute()` function. To remediate this issue, use SQLAlchemy statements + which are built with query parameterization and therefore not vulnerable + to sql injection. + + If for some reason this is not feasible, ensure calls including user-supplied + data pass it in to the `params` parameter of the `execute()` method. + Below is an example using `execute()`, passing in user-supplied data as `params`. + This will treat the query as a parameterized query and `params` as strictly data, + preventing any possibility of SQL Injection. + + ``` + name = request.args.get('name') + req = text('SELECT * FROM student WHERE firstname = :x') + result = db.session.execute(req, {"x":name}) + ``` + For more information on QuerySets see: + - https://docs.djangoproject.com/en/4.2/ref/models/querysets/#queryset-api + For more information on SQL Injections see OWASP: + - https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html + metadata: + security-severity: High + cwe: CWE-89 + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + category: security + shortDescription: + Improper neutralization of special elements used in an SQL + Command ('SQL Injection') + mode: taint + pattern-sources: + - pattern-either: + - pattern: flask.request.$ANYTHING + - patterns: + - pattern-inside: | + @$APP.route(...) + def $FUNC(..., $ROUTEVAR, ...): + ... + - pattern: $ROUTEVAR + pattern-sinks: + - patterns: + - pattern-either: + - pattern: | + <... "$QUERYLIKE" ...> + - metavariable-regex: + metavariable: $QUERYLIKE + regex: .*\b(?i)(SELECT .+ FROM|WHERE|DELETE FROM|INSERT INTO| CREATE TABLE|UPDATE .+ SET|ALTER TABLE|ALTER COLUMN|DROP COLUMN|DROP TABLE|ORDER BY)\b.* + severity: ERROR +- id: python_flask_rule-flask-open-redirect + languages: + - "python" + patterns: + - pattern-inside: | + @$APP.route(...) + def $X(...): + ... + - pattern-not-inside: | + @$APP.route(...) + def $X(...): + ... + if <... werkzeug.urls.url_parse($V) ...>: + ... + - pattern-either: + - pattern: "flask.redirect(<... flask.request.$W.get(...) ...>, ...)" + - pattern: "flask.redirect(<... flask.request.$W[...] ...>, ...)" + - pattern: "flask.redirect(<... flask.request.$W(...) ...>, ...)" + - pattern: "flask.redirect(<... flask.request.$W ...>, ...)" + - pattern: | + $V = flask.request.$W.get(...) + ... + flask.redirect(<... $V ...>, ...) + - pattern: | + $V = flask.request.$W[...] + ... + flask.redirect(<... $V ...>, ...) + - pattern: | + $V = flask.request.$W(...) + ... + flask.redirect(<... $V ...>, ...) + - pattern: | + $V = flask.request.$W + ... + flask.redirect(<... $V ...>, ...) + - pattern-not: "flask.redirect(flask.request.path)" + - pattern-not: "flask.redirect(flask.request.path + ...)" + - pattern-not: "flask.redirect(f\"{flask.request.path}...\")" + message: >- + Data from request is passed to redirect(). This is an open redirect and could be exploited. Consider using 'url_for()' + to generate links to known locations. If you must use a URL to unknown pages, consider using 'urlparse()' or similar + and checking if the 'netloc' property is the same as your site's host name. For example: + + Example: + ```python + from flask import Flask, request, redirect, url_for + from urllib.parse import urlparse + + app = Flask(__name__) + + @app.route('/login') + def login(): + next = request.args.get('next') + if not next: + next = url_for('index') + if urlparse(next).netloc != urlparse(request.url).netloc: + return redirect(url_for('index')) + return redirect(next) + ``` + See the references for more information. + metadata: + cwe: "CWE-601" + shortDescription: "URL redirection to untrusted site ('Open Redirect')" + owasp: + - "A01:2021-Broken Access Control" + - "A5:2017-Broken Access Control" + category: "security" + security-severity: "MEDIUM" + references: | + - https://flask-login.readthedocs.io/en/latest/#login-example + - https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html#dangerous-url-redirect-example-1 + - https://docs.python.org/3/library/urllib.parse.html#url-parsing + technology: + - "flask" + subcategory: + - "audit" + likelihood: "LOW" + impact: "MEDIUM" + confidence: "LOW" + severity: "WARNING" +- id: python_jwt_rule-jwt-none-alg + languages: + - "python" + message: | + Detected use of the 'none' algorithm in a JWT token. + The 'none' algorithm assumes the integrity of the token has already + been verified. This would allow a malicious actor to forge a JWT token + that will automatically be verified. Do not explicitly use the 'none' + algorithm. Instead, use an algorithm such as 'HS256'. + metadata: + cwe: "CWE-327" + shortDescription: "Use of a Broken or Risky Cryptographic Algorithm" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + category: "security" + security-severity: "MEDIUM" + source-rule-url: "https://semgrep.dev/blog/2020/hardcoded-secrets-unverified-tokens-and-other-common-jwt-mistakes/" + technology: + - "jwt" + references: + - "https://owasp.org/Top10/A02_2021-Cryptographic_Failures" + subcategory: + - "vuln" + likelihood: "MEDIUM" + impact: "MEDIUM" + confidence: "MEDIUM" + severity: "ERROR" + pattern-either: + - pattern: |- + jwt.encode(...,algorithm="none",...) + - pattern: |- + jwt.decode(...,algorithms=[...,"none",...],...) +- id: python_pyramid_rule-pyramid-csrf-origin-check + patterns: + - pattern-inside: | + $CONFIG.set_default_csrf_options(..., check_origin=$CHECK_ORIGIN, ...) + - pattern: | + $CHECK_ORIGIN + - metavariable-comparison: + metavariable: $CHECK_ORIGIN + comparison: $CHECK_ORIGIN == False + message: | + Automatic check of the referrer for cross-site request forgery tokens + has been explicitly disabled globally, which might leave views unprotected + when an unsafe CSRF storage policy is used. By passing `check_origin=False` + to `set_default_csrf_options()` method, you opt out of checking the origin + of the domain in the referrer header or the origin header, which can make + the application vulnerable to CSRF attacks, specially if CSRF token is not + properly implemented. + CSRF attacks are a type of exploit where an attacker tricks a user into + executing unwanted actions on a web application in which they are authenticated. + If a user is logged into a web application, an attacker could create a malicious + link or script on another site that causes the user's browser to make a request + to the web application, carrying out an action without the user's consent. + + To mitigate this vulnerability, use + 'pyramid.config.Configurator.set_default_csrf_options(check_origin=True)' + to turn the automatic check for all unsafe methods (per RFC2616). + + Secure Code Example: + ``` + def safe(config): + config.set_csrf_storage_policy(CookieCSRFStoragePolicy()) + config.set_default_csrf_options(check_origin=True) + ``` + languages: + - "python" + severity: "WARNING" + metadata: + shortDescription: "Cross-site request forgery (CSRF)" + category: "security" + cwe: "CWE-352" + owasp: + - "A5:2017-Broken Access Control" + - "A01:2021-Broken Access Control" + security-severity: "MEDIUM" + technology: + - "pyramid" + references: + - "https://owasp.org/Top10/A01_2021-Broken_Access_Control" + - "https://docs.pylonsproject.org/projects/pyramid/en/latest/narr/security.html" + cwe2022-top25: "true" + cwe2021-top25: "true" + subcategory: + - "vuln" + likelihood: "LOW" + impact: "LOW" + confidence: "MEDIUM" + license: "Commons Clause License Condition v1.0[LGPL-2.1-only]" + vulnerability_class: + - "Cross-Site Request Forgery (CSRF)" +- id: ruby_cookie_rule-CheckCookieStoreSessionSecurityAttributes + patterns: + - pattern-either: + - patterns: + - pattern: | + :$KEY => false + - pattern-inside: | + ActionController::Base.session = {...} + - pattern: | + $MODULE::Application.config.session_store :cookie_store, ..., :$KEY => false, ... + - pattern: | + $CLASS.application.config.session_store :cookie_store, ..., $KEY: false, ... + - metavariable-regex: + metavariable: $KEY + regex: ^(session_)?(http_?only|secure)$ + message: | + The detected issue pertains to a Rails application where the session + configuration, specifically using cookie_store, has been identified + with the $KEY attribute set to false. This setting is potentially + insecure because it may relate to crucial security attributes such + as HttpOnly or Secure flags not being enforced. In the context of + web applications, these flags play a vital role in enhancing session + security: + + - HttpOnly Flag: When enabled, this flag prevents client-side scripts + from accessing the cookie. This mitigation is crucial for reducing + the risk of cross-site scripting (XSS) attacks, where an attacker + might attempt to steal session cookies. + - Secure Flag: This flag ensures that cookies are sent over secure, + encrypted connections only (HTTPS). It's a critical security measure + that helps prevent cookies from being intercepted by attackers when + transmitted over an unencrypted connection. + + To mitigate the identified security risk and ensure that your Rails + application's session cookies are securely configured. + + Secure Code Example: + ``` + # config/initializers/session_store.rb + Rails.application.config.session_store :cookie_store, key: '_your_app_session', + httponly: true, + secure: Rails.env.production? + ``` + languages: + - "ruby" + severity: "INFO" + metadata: + category: "security" + shortDescription: "Sensitive cookie without 'HttpOnly' and 'Secure' flags" + owasp: + - "A6:2017-Security Misconfiguration" + - "A05:2021-Security Misconfiguration" + cwe: "CWE-1004" + technology: + - "ruby" + - "rails" + security-severity: "LOW" + references: + - "https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/06-Session_Management_Testing/02-Testing_for_Cookies_Attributes" + - "https://github.com/semgrep/semgrep-rules/blob/develop/ruby/rails/security/brakeman/check-cookie-store-session-security-attributes.yaml" + +- id: ruby_cookie_rule-CookieSerialization + message: | + The rule warns of a significant security risk in applications that use + Ruby's Marshal module for deserializing cookies. Marshal can serialize + and deserialize Ruby objects, which, while powerful, poses a risk if + misused. If an attacker crafts a malicious cookie that is deserialized, + it could lead to remote code execution (RCE) on the server due to + Marshal.load's ability to execute code in deserialized objects. To mitigate + this risk, developers are advised to switch from Marshal to JSON for cookie + serialization. JSON is safer as it cannot execute arbitrary code, reducing + the threat of RCE vulnerabilities from deserialized user data. The hybrid + check is just to warn users to migrate to :json for best practice. + + Secure code example: + ``` + # In Rails, configure the cookie serializer to :json + # config/initializers/cookies_serializer.rb + Rails.application.config.action_dispatch.cookies_serializer = :json + ``` + + Additionally, always validate and sanitize user-supplied data as much + as possible, even when using JSON, to further secure your application + against various injection attacks. + languages: + - "ruby" + metadata: + shortDescription: "Improper control of generation of code ('Code Injection')" + category: "security" + cwe: "CWE-94" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + technology: + - "ruby" + security-severity: "HIGH" + references: + - "https://github.com/semgrep/semgrep-rules/blob/develop/ruby/lang/security/cookie-serialization.yaml" + - "https://robertheaton.com/2013/07/22/how-to-hack-a-rails-app-using-its-secret-token/" + severity: "ERROR" + pattern-either: + - pattern: | + Rails.application.config.action_dispatch.cookies_serializer = :marshal + - pattern: | + Rails.application.config.action_dispatch.cookies_serializer = :hybrid +- id: ruby_crypto_rule-InsufficientRSAKeySize + message: | + The RSA key size $SIZE is insufficent by NIST standards. It is + recommended to use a key length of 2048 or higher. The RSA algorithm, + being widely used for secure data transmission, relies on key size + for its security. Smaller key sizes (e.g., 1024 bits and below) are + more susceptible to brute-force attacks, where an attacker uses + computational power to decrypt data or forge signatures. + + To address this security concern, ensure that all RSA keys are + generated with a size of 2048 bits or more. + + Folowing is a secure code example: + ``` + require 'openssl' + + # Generate a new RSA key of 2048 bits + rsa_key = OpenSSL::PKey::RSA.new(2048) + + # To export the RSA key + private_key = rsa_key.to_pem + public_key = rsa_key.public_key.to_pem + ``` + languages: + - "ruby" + severity: "WARNING" + metadata: + category: "security" + shortDescription: "Inadequate encryption strength" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + cwe: "CWE-326" + technology: + - "ruby" + security-severity: "MEDIUM" + references: + - "https://github.com/semgrep/semgrep-rules/blob/develop/ruby/lang/security/insufficient-rsa-key-size.yaml" + - "https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-57Pt3r1.pdf" + patterns: + - pattern-either: + - pattern: OpenSSL::PKey::RSA.generate($SIZE,...) + - pattern: OpenSSL::PKey::RSA.new($SIZE, ...) + - patterns: + - pattern-either: + - patterns: + - pattern-inside: | + $ASSIGN = $SIZE + ... + - pattern-either: + - pattern: OpenSSL::PKey::RSA.new($ASSIGN, ...) + - pattern: OpenSSL::PKey::RSA.generate($ASSIGN, ...) + - patterns: + - pattern-inside: | + def $METHOD1(...) + ... + $ASSIGN = $SIZE + ... + end + ... + - pattern-either: + - pattern: OpenSSL::PKey::RSA.new($ASSIGN, ...) + - pattern: OpenSSL::PKey::RSA.generate($ASSIGN, ...) + - metavariable-comparison: + metavariable: $SIZE + comparison: $SIZE < 2048 +- id: ruby_crypto_rule-WeakHashesMD5 + message: | + The MD5 hashing algorithm is considered cryptographically weak and + vulnerable to collision attacks, where two different inputs generate + the same output hash. When used for hashing sensitive data, attackers + can exploit this weakness to generate collisions, allowing them to bypass + security checks or masquerade malicious data as legitimate. This + vulnerability is particularly critical in authentication mechanisms, + digital signatures, SSL/TLS certificates, and data integrity checks. + + Remediation: + To mitigate this vulnerability, replace the MD5 hashing algorithm with + stronger cryptographic hash functions, such as SHA-256 or SHA-3. These + algorithms offer significantly improved security and are resistant to + collision attacks, making them suitable for cryptographic purposes in + modern applications. + + Secure Code example: + ``` + require 'openssl' + + data = "sensitive information" + # Using SHA-256 + digest = OpenSSL::Digest::SHA256.new + hash = digest.digest(data) + hex_hash = digest.hexdigest(data) + + # Using SHA-3 (256 bits) + digest = OpenSSL::Digest::SHA3.new(256) + hash2 = digest.digest(data) + hex_hash2 = digest.hexdigest(data) + ``` + metadata: + shortDescription: "Use of weak hash" + category: "security" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + cwe: "CWE-328" + security-severity: "MEDIUM" + references: + - "https://github.com/semgrep/semgrep-rules/blob/develop/ruby/lang/security/weak-hashes-md5.yaml" + - "https://www.ibm.com/support/pages/security-bulletin-vulnerability-md5-signature-and-hash-algorithm-affects-sterling-integrator-and-sterling-file-gateway-cve-2015-7575" + technology: + - "ruby" + languages: + - "ruby" + severity: "WARNING" + pattern-either: + - pattern: Digest::MD5.base64digest $X + - pattern: Digest::MD5.hexdigest $X + - pattern: Digest::MD5.digest $X + - pattern: Digest::MD5.new + - pattern: OpenSSL::Digest::MD5.base64digest $X + - pattern: OpenSSL::Digest::MD5.hexdigest $X + - pattern: OpenSSL::Digest::MD5.digest $X + - pattern: OpenSSL::Digest::MD5.new +- id: ruby_crypto_rule-WeakHashesSHA1 + message: | + The SHA-1 hashing algorithm is no longer considered secure for + cryptographic applications due to its vulnerability to collision attacks, + where two different inputs produce the same output hash. SHA-1's + susceptibility to collision attacks undermines the security of + cryptographic operations, allowing attackers to forge signatures or + manipulate data without detection. This poses significant risks in + authentication systems, data integrity validations, and secure + communications. + + Remediation: To mitigate this vulnerability, replace the SHA1 hashing + algorithm with stronger cryptographic hash functions, such as SHA-256 + or SHA-3. These algorithms offer significantly improved security and + are resistant to collision attacks, making them suitable for cryptographic + purposes in modern applications. + + Secure Code example : + ``` + require 'openssl' + + data = "sensitive information" + # Using SHA-256 + digest = OpenSSL::Digest::SHA256.new + hash = digest.digest(data) + hex_hash = digest.hexdigest(data) + + # Using SHA-3 (256 bits) + digest = OpenSSL::Digest::SHA3.new(256) + hash2 = digest.digest(data) + hex_hash2 = digest.hexdigest(data) + ``` + metadata: + shortDescription: "Use of weak hash" + category: "security" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + cwe: "CWE-328" + security-severity: "MEDIUM" + references: + - "https://github.com/semgrep/semgrep-rules/blob/develop/ruby/lang/security/weak-hashes-sha1.yaml" + - "https://security.googleblog.com/2017/02/announcing-first-sha1-collision.html" + - "https://shattered.io/" + technology: + - "ruby" + languages: + - "ruby" + severity: "WARNING" + pattern-either: + - pattern: Digest::SHA1.$FUNC + - pattern: OpenSSL::Digest::SHA1.$FUNC + - pattern: OpenSSL::HMAC.$FUNC("sha1",...) +- id: ruby_csrf_rule-MissingCSRFProtection + patterns: + - pattern: | + class $CONTROLLER < ActionController::Base + ... + end + - pattern-not: | + class $CONTROLLER < ActionController::Base + ... + protect_from_forgery + end + message: | + Detected controller which does not enable cross-site request forgery + protections using `protect_from_forgery`. When a Rails application does + not use `protect_from_forgery` in its controllers, it is vulnerable to + CSRF attacks. This vulnerability can allow attackers to submit unauthorized + requests on behalf of authenticated users, potentially leading to + unauthorized actions being performed. + To mitigate this risk, Rails offers the `protect_from_forgery` method, + which integrates CSRF token verification in every form submitted to + your application, ensuring that requests are legitimate. + Add `protect_from_forgery with: :exception` to your controller class. + The `with: :exception` option configures Rails to raise an exception + if a CSRF token cannot be verified, providing an additional layer of security. + This approach ensures that unverified requests do not proceed silently, + allowing for appropriate error handling and response measures. + + Secure Code Example: + ``` + class YourController < ApplicationController + protect_from_forgery with: :exception + # Your controller actions here + end + ``` + For more information on CSRF, see OWASP guide: + https://owasp.org/www-community/attacks/csrf + languages: + - "ruby" + metadata: + shortDescription: "Cross-site request forgery (CSRF)" + category: "security" + cwe: "CWE-352" + owasp: + - "A5:2017-Broken Access Control" + - "A01:2021-Broken Access Control" + security-severity: "MEDIUM" + technology: + - "ruby" + references: + - "https://github.com/semgrep/semgrep-rules/blob/develop/ruby/lang/security/missing-csrf-protection.yaml" + - "https://owasp.org/Top10/A01_2021-Broken_Access_Control" + severity: "WARNING" +- id: ruby_deserialization_rule-BadDeserialization + mode: taint + pattern-sources: + - pattern-either: + - pattern: params + - pattern: cookies + pattern-sinks: + - pattern-either: + - pattern: | + Marshal.load(...) + - pattern: | + Marshal.restore(...) + - pattern: | + Oj.object_load(...) + - pattern: | + Oj.load($X) + message: | + In Ruby, objects can be serialized into strings using various methods + and later reconstituted into objects. The `load` and `object_load` + methods, associated with modules like Marshal and CSV, is particularly + risky when used to deserialize data from untrusted sources. + If an attacker is able to manipulate the serialized data, they could + execute arbitrary code on the system when the data is deserialized. + This vulnerability can lead to remote code execution (RCE), where an + attacker gains the ability to execute commands on the host machine. + The Marshal and CSV modules are often used for serialization and + deserialization in Ruby but they do not inherently sanitize or validate + the data being processed. This makes them unsafe for handling input from + untrusted sources. + + To mitigate the risks associated with unsafe deserialization, it is + recommended to: + - Avoid deserializing from untrusted sources + - Use JSON for serialization/deserialization as JSON is considered + safer for data interchange between systems. However, it's crucial + to use JSON securely by validating and sanitizing the input before + deserialization. + + Secure Code Example: + ``` + require 'json' + + def safe_deserialize(json_data) + # Validate and sanitize json_data before parsing + begin + parsed_data = JSON.parse(json_data) + return parsed_data + rescue JSON::ParserError => e + puts "Error parsing JSON data: #{e.message}" + return nil + end + end + + # Example usage + # Example of input JSON string + json_input = '{"name": "John Doe", "age": 30}' + user_data = safe_deserialize(json_input) + puts user_data.inspect if user_data + ``` + + Always ensure that any data deserialized from JSON (or any format) is + validated and sanitized according to the context of your application + to prevent injection attacks or other security issues. + languages: + - "ruby" + severity: "ERROR" + metadata: + shortDescription: "Deserialization of untrusted data" + category: "security" + cwe: "CWE-502" + owasp: + - "A8:2017-Insecure Deserialization" + - "A08:2021-Software and Data Integrity Failures" + security-severity: "HIGH" + technology: + - "ruby" + references: + - "https://groups.google.com/g/rubyonrails-security/c/61bkgvnSGTQ/m/nehwjA8tQ8EJ" + - "https://github.com/semgrep/semgrep-rules/blob/develop/ruby/lang/security/bad-deserialization.yaml" +- id: ruby_deserialization_rule-BadDeserializationEnv + mode: taint + pattern-sources: + - pattern-either: + - pattern: request.env + pattern-sinks: + - pattern-either: + - pattern: | + Marshal.load(...) + - pattern: | + Marshal.restore(...) + - pattern: | + Oj.object_load(...) + - pattern: | + Oj.load($X) + message: | + In Ruby, objects can be serialized into strings using various methods + and later reconstituted into objects. The `load` and `object_load` + methods, associated with modules like Marshal and CSV, is particularly + risky when used to deserialize data from untrusted sources. + If an attacker is able to manipulate the serialized data, they could + execute arbitrary code on the system when the data is deserialized. + This vulnerability can lead to remote code execution (RCE), where an + attacker gains the ability to execute commands on the host machine. + The Marshal and CSV modules are often used for serialization and + deserialization in Ruby but they do not inherently sanitize or validate + the data being processed. This makes them unsafe for handling input from + untrusted sources. + + To mitigate the risks associated with unsafe deserialization, it is + recommended to: + - Avoid deserializing from untrusted sources + - Use JSON for serialization/deserialization as JSON is considered + safer for data interchange between systems. However, it's crucial + to use JSON securely by validating and sanitizing the input before + deserialization. + + Secure Code Example: + ``` + require 'json' + + def safe_deserialize(json_data) + # Validate and sanitize json_data before parsing + begin + parsed_data = JSON.parse(json_data) + return parsed_data + rescue JSON::ParserError => e + puts "Error parsing JSON data: #{e.message}" + return nil + end + end + + # Example usage + # Example of input JSON string + json_input = '{"name": "John Doe", "age": 30}' + user_data = safe_deserialize(json_input) + puts user_data.inspect if user_data + ``` + + Always ensure that any data deserialized from JSON (or any format) is + validated and sanitized according to the context of your application + to prevent injection attacks or other security issues. + languages: + - "ruby" + severity: "ERROR" + metadata: + shortDescription: "Deserialization of untrusted data" + category: "security" + cwe: "CWE-502" + owasp: + - "A8:2017-Insecure Deserialization" + - "A08:2021-Software and Data Integrity Failures" + security-severity: "HIGH" + technology: + - "ruby" + references: + - "https://groups.google.com/g/rubyonrails-security/c/61bkgvnSGTQ/m/nehwjA8tQ8EJ" + - "https://github.com/semgrep/semgrep-rules/blob/develop/ruby/lang/security/bad-deserialization-env.yaml" +- id: ruby_deserialization_rule-BadDeserializationYAML + patterns: + - pattern: | + YAML.$LOAD($...ARGS) + - pattern-not: | + YAML.$LOAD(..., safe: true, ...) + - pattern-not: | + YAML.$LOAD("...", ...) + - pattern-not-inside: | + $FILE = File.read("...", ...) + ... + YAML.$LOAD(..., $FILE, ...) + - pattern-not-inside: | + $FILENAME = "..." + ... + $FILE = File.read($FILENAME, ...) + ... + YAML.$LOAD(..., $FILE, ...) + - pattern-not-inside: | + YAML.$LOAD(..., File.read("...", ...), ...) + - metavariable-regex: + metavariable: $LOAD + regex: load(?:_stream)?\b|parse_stream + fix: Psych.safe_load($...ARGS) + message: | + Unsafe deserialization from YAML. + YAML is a popular format for configuration files in Ruby applications + due to its readability and simplicity. However, the `load` method + provided by Ruby's YAML module can be dangerous when used to deserialize + data from untrusted sources. The method can instantiate objects based + on the YAML input, which can lead to remote code execution (RCE) if the + input contains malicious code. + + To mitigate the risk of RCE through unsafe deserialization practices, + consider the following recommendations: + - Prefer JSON for untrusted data: JSON is generally safer for + deserializing untrusted data because, by design, it does not support + the execution of arbitrary code. Ensure that any JSON deserialization + is performed with caution, validating and sanitizing the input before + use. + - Use safe YAML loading methods: If you must use YAML, prefer safe + loading methods like `safe_load` instead of `load`. The `safe_load` method + limits the objects that can be deserialized, reducing the risk of + executing arbitrary code. + - Static YAML files: Loading YAML from static, trusted files (like + configuration files that are not exposed to user input) is generally + safe. Ensure these files are securely managed and not modifiable by + untrusted sources. + + Secure Code Example: + ``` + require 'yaml' + require 'json' + + # Safe YAML deserialization + def safe_load_yaml(file_path) + YAML.safe_load(File.read(file_path), [Date, Time], [], true) + end + + # Example of safely loading a static YAML file + config_data = safe_load_yaml('config.yml') + puts config_data.inspect + + # Safe JSON deserialization + def safe_load_json(json_input) + # Always validate and sanitize input before deserialization + JSON.parse(json_input) + end + + # Example JSON input + json_input = '{"name": "Jack Monroe", "age": 30}' + user_data = safe_load_json(json_input) + puts user_data.inspect + ``` + languages: + - "ruby" + severity: "ERROR" + metadata: + shortDescription: "Deserialization of untrusted data" + category: "security" + cwe: "CWE-502" + owasp: + - "A8:2017-Insecure Deserialization" + - "A08:2021-Software and Data Integrity Failures" + security-severity: "HIGH" + technology: + - "ruby" + - "yaml" + references: + - "https://groups.google.com/g/rubyonrails-security/c/61bkgvnSGTQ/m/nehwjA8tQ8EJ" + - "https://github.com/semgrep/semgrep-rules/blob/develop/ruby/lang/security/bad-deserialization-yaml.yaml" +- id: ruby_error_rule-DivideByZero + mode: taint + pattern-sources: + - patterns: + - pattern: $VAR + - metavariable-regex: + metavariable: $VAR + regex: ^\d*(?!\.)$ + pattern-sinks: + - patterns: + - pattern-inside: $NUMBER / 0 + - pattern: $NUMBER + message: | + A ZeroDivisionError exception has been detected, this occurs when an arithmetic operation attempts to + divide a number by zero. This can happen in various contexts, such as + processing user inputs, performing calculations with variables, or + working with data from external sources. Such errors not only disrupt + the normal flow of the application but also can be exploited in certain + scenarios to cause harm (eg. possible dos) or extract information based + on the application's response to the error. + + To prevent ZeroDivisionError exceptions and ensure application robustness: + - Error handling: Implement error handling around division operations to + catch and manage ZeroDivisionError gracefully. + - Validation: Always validate inputs that are used in division operations + to ensure they are not zero or unexpected values. + languages: + - "ruby" + severity: "WARNING" + metadata: + shortDescription: "Divide a number by zero" + category: "security" + cwe: "CWE-369" + owasp: + - "A6:2017-Security Misconfiguration" + - "A04:2021-Insecure Design" + security-severity: "LOW" + references: + - "https://github.com/semgrep/semgrep-rules/blob/develop/ruby/lang/security/divide-by-zero.yaml" + technology: + - "ruby" + + +- id: ruby_escaping_rule-JSONEntityEscape + pattern-either: + - pattern: | + ActiveSupport.escape_html_entities_in_json = false + - pattern: | + config.active_support.escape_html_entities_in_json = false + message: | + This rule checks if HTML escaping is globally disabled for JSON output, + which can lead to Cross-Site Scripting (XSS) vulnerabilities. + XSS attacks allow attackers to inject malicious scripts into web pages + viewed by other users, compromising the integrity and confidentiality + of user data. When HTML escaping is disabled, special HTML characters + in JSON output are not converted to their entity equivalents, making + it possible for an attacker to inject executable scripts into the web + application's output. + + To mitigate this risk, ensure that HTML escaping is enabled when + generating JSON output, particularly in web applications + that dynamically insert user-generated content into the DOM. + + Secure Code Example: + ``` + # For an initializer configuration (e.g., in config/initializers/active_support.rb) + # Enable HTML entity escaping in JSON to prevent XSS + ActiveSupport.escape_html_entities_in_json = true + + # For application-wide configuration (e.g., in config/application.rb) + module YourApplication + class Application < Rails::Application + # Enable HTML entity escaping in JSON to prevent XSS + config.active_support.escape_html_entities_in_json = true + end + end + ``` + languages: + - "ruby" + metadata: + shortDescription: "Improper neutralization of input during web page generation + ('Cross-site Scripting')" + category: "security" + cwe: "CWE-79" + owasp: + - "A7:2017-Cross-Site Scripting (XSS)" + - "A03:2021-Injection" + security-severity: "MEDIUM" + technology: + - "rails" + references: + - "https://owasp.org/Top10/A03_2021-Injection" + - "https://github.com/semgrep/semgrep-rules/blob/develop/ruby/lang/security/json-entity-escape.yaml" + severity: "WARNING" +- id: ruby_eval_rule-NoEval + message: | + The `eval` method in Ruby executes a string argument as Ruby code. When + `eval` is used with input that can be controlled or manipulated by an + external user, it can allow arbitrary code execution. This + means an attacker could potentially execute malicious code on the server, + leading to unauthorized access, data leakage, or server compromise. + + Remediation Steps: + - Validate and sanitize input: If there's an absolute necessity to use + `eval`, ensure that any user input is rigorously validated and sanitized + to remove potentially harmful code. However, this is generally not + recommended due to the difficulty of securely sanitizing code. + - Use safer alternatives: Depending on the requirement, consider using + safer alternatives to `eval`, such as `send` for calling methods dynamically + or employing DSLs (Domain-Specific Languages) and safe parsing libraries + designed for specific tasks. + + Secure Code Example: + ``` + class Calculator + def add(a, b) + a + b + end + end + + # Safer alternative using send + calculator = Calculator.new + method = params[:operation] # Example: 'add' or 'subtract' + a = params[:a].to_i + b = params[:b].to_i + + if calculator.respond_to?(method) + result = calculator.send(method, a, b) + else + puts "Invalid operation" + end + ``` + + In this example, `send` is used to dynamically call a method on the + Calculator object based on user input. This approach is safer than + eval because it strictly limits the operations to those defined in + the class, preventing arbitrary code execution. + severity: "ERROR" + metadata: + cwe: "CWE-95" + shortDescription: "Improper neutralization of directives in dynamically evaluated + code ('Eval Injection')" + category: "security" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "HIGH" + references: + - "https://owasp.org/Top10/A03_2021-Injection" + - "https://github.com/semgrep/semgrep-rules/blob/develop/ruby/lang/security/no-eval.yaml" + technology: + - "rails" + languages: + - "ruby" + mode: taint + pattern-sources: + - pattern-either: + - pattern: params + - pattern: cookies + - patterns: + - pattern: | + RubyVM::InstructionSequence.compile(...) + - pattern-not: | + RubyVM::InstructionSequence.compile("...") + pattern-sinks: + - patterns: + - pattern-either: + - pattern: $X.eval + - pattern: $X.class_eval + - pattern: $X.instance_eval + - pattern: $X.module_eval + - pattern: $X.eval(...) + - pattern: $X.class_eval(...) + - pattern: $X.instance_eval(...) + - pattern: $X.module_eval(...) + - pattern: eval(...) + - pattern: class_eval(...) + - pattern: module_eval(...) + - pattern: instance_eval(...) + - pattern-not: $M("...",...) +- id: ruby_exceptions_rule-DetailedExceptions + patterns: + - pattern-either: + - patterns: + - pattern: | + config.consider_all_requests_local = true + - patterns: + - pattern-inside: | + class $CONTROLLER < ApplicationController + ... + end + - pattern: | + def show_detailed_exceptions? (...) + ... + return $RETURN + end + - metavariable-pattern: + metavariable: $RETURN + patterns: + - pattern-not: | + false + message: | + The `consider_all_requests_local` setting was found set to true, which enables detailed exception reports. This setting, + while useful during development for debugging purposes, can + inadvertently expose sensitive system or application information + to end users when enabled in production environments. Such + information exposure could potentially aid attackers in crafting + further attacks against the system. + + It is advisable to disable detailed exception reporting in production + environments to prevent the leakage of sensitive information. + + Secure Configuration Example: + ``` + # config/environments/production.rb + Rails.application.config.consider_all_requests_local = false + ``` + languages: + - "ruby" + severity: "WARNING" + metadata: + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A05:2021-Security Misconfiguration" + shortDescription: "Generation of error message containing sensitive information" + cwe: "CWE-209" + category: "security" + security-severity: "MEDIUM" + technology: + - "rails" + references: + - "https://github.com/semgrep/semgrep-rules/blob/develop/ruby/rails/security/audit/detailed-exceptions.yaml" +- id: ruby_file_rule-AvoidTaintedFileAccess + mode: taint + pattern-sources: + - pattern: params + - pattern: cookies + - pattern: request.env + pattern-sinks: + - patterns: + - pattern-either: + - pattern: Dir.$X(...) + - pattern: File.$X(...) + - pattern: IO.$X(...) + - pattern: Kernel.$X(...) + - pattern: PStore.$X(...) + - pattern: Pathname.$X(...) + - metavariable-pattern: + metavariable: $X + patterns: + - pattern-either: + - pattern: chdir + - pattern: chroot + - pattern: delete + - pattern: entries + - pattern: foreach + - pattern: glob + - pattern: install + - pattern: lchmod + - pattern: lchown + - pattern: link + - pattern: load + - pattern: load_file + - pattern: makedirs + - pattern: move + - pattern: new + - pattern: open + - pattern: read + - pattern: readlines + - pattern: rename + - pattern: rmdir + - pattern: safe_unlink + - pattern: symlink + - pattern: syscopy + - pattern: sysopen + - pattern: truncate + - pattern: unlink + message: | + The application dynamically constructs file or path information with user input. When an application uses data from + untrusted sources (like `params`, `cookies`, or `request.env`) to perform + actions on the file system, it opens up potential vulnerabilities. + A malicious actor could exploit this to access, modify, or delete + files they shouldn't have access to, leading to information disclosure, + data loss, or server compromise. This type of vulnerability is often + referred to as a File Inclusion vulnerability or Path Traversal attack, + depending on the nature of the exploit. + + To mitigate these risks, follow these best practices: + - Validate and sanitize input: Ensure all user inputs are strictly + validated and sanitized to prevent path traversal characters (like `../`) + or other malicious patterns. Only allow filenames or paths that match + specific, safe patterns. + - Use secure libraries: Utilize libraries or frameworks that abstract + file access in a secure manner, automatically handling the risks + associated with raw user input. + - Least privilege principle: Run your application with the minimum + necessary file system permissions. Restrict the application's access + to only those directories and files it absolutely needs. + - Directory whitelisting: Maintain an allow list of permitted directories + for file operations, rejecting any requests for paths outside of these + directories. + + Secure Code Example: + ``` + def safe_file_read(filename) + # Define a list of allowed files or use regex to validate the filename format + allowed_files = ['allowed_file.txt', 'another_safe_file.txt'] + + if allowed_files.include?(filename) + file_path = Rails.root.join('safe_directory', filename) + content = File.read(file_path) + return content + else + raise "Access to the requested file is not allowed." + end + end + ``` + languages: + - "ruby" + severity: "WARNING" + metadata: + owasp: + - "A5:2017-Broken Access Control" + - "A01:2021-Broken Access Control" + cwe: "CWE-22" + shortDescription: "Improper limitation of a pathname to a restricted directory + ('Path Traversal')" + references: + - "https://github.com/semgrep/semgrep-rules/blob/develop/ruby/rails/security/audit/avoid-tainted-file-access.yaml" + category: "security" + security-severity: "MEDIUM" + technology: + - "rails" +- id: ruby_file_rule-CheckRenderLocalFileInclude + mode: taint + pattern-sources: + - patterns: + - pattern: params[...] + pattern-sinks: + - patterns: + - pattern-either: + - pattern: | + render ..., file: $X + - pattern: | + render ..., inline: $X + - pattern: | + render ..., template: $X + - pattern: | + render ..., action: $X + - pattern: | + render $X, ... + - focus-metavariable: $X + pattern-sanitizers: + - patterns: + - pattern: $MAP[...] + - metavariable-pattern: + metavariable: $MAP + patterns: + - pattern-not-regex: params + - pattern: File.basename(...) + message: | + The application dynamically constructs file or path information with user input when calling the `render` function. This can allow end + users to request arbitrary local files which may result in leaking + sensitive information persisted on disk. Where possible, avoid letting + users specify template paths for `render`. If you must allow user input, + use an allow-list of known templates or normalize the user-supplied value + with `File.basename(...)`. + + To mitigate this vulnerability, follow these steps: + - Avoid direct user input: If possible, do not use user input + to determine file paths. Use a mapping of user input to server-side + defined file paths instead. + - Use `File.basename`: If user input must be used to specify a file, + ensure that the input is normalized using `File.basename` to extract + the filename without any directory path. This prevents directory + traversal attacks. + - Path allow listing: Implement an allow list of permitted files or + directories and check user input against this list before processing. + + Secure Code Example: + ``` + class PagesController < ApplicationController + # Allowlist + def show + valid_pages = ['home', 'about_us', 'contact'] + if valid_pages.include?(params[:page]) + render params[:page] + else + render 'not_found' + end + end + + # Sanitizing User Input + def show + # Sanitize the user input to extract just the file name + page = File.basename(params[:page]) + # Optionally, further validate the sanitized input against an allow-list or other criteria + render page + end + end + ``` + languages: + - "ruby" + severity: "WARNING" + metadata: + owasp: + - "A5:2017-Broken Access Control" + - "A01:2021-Broken Access Control" + cwe: "CWE-22" + shortDescription: "Improper limitation of a pathname to a restricted directory + ('Path Traversal')" + references: + - "https://owasp.org/www-project-web-security-testing-guide/v42/4-Web_Application_Security_Testing/07-Input_Validation_Testing/11.1-Testing_for_Local_File_Inclusion" + - "https://github.com/semgrep/semgrep-rules/blob/develop/ruby/rails/security/brakeman/check-render-local-file-include.yaml" + category: "security" + security-severity: "MEDIUM" + technology: + - "rails" +- id: ruby_file_rule-CheckSendFile + mode: taint + pattern-sources: + - pattern-either: + - pattern: | + cookies[...] + - patterns: + - pattern: | + cookies. ... .$PROPERTY[...] + - metavariable-regex: + metavariable: $PROPERTY + regex: (?!signed|encrypted) + - pattern: | + params[...] + - pattern: | + request.env[...] + pattern-sinks: + - patterns: + - pattern: | + send_file ... + message: | + The application dynamically constructs file or path information with user input when calling + the `send_file` method in Ruby. This practice can lead to a serious + security vulnerability known as Local File Inclusion (LFI), allowing + attackers to read arbitrary files on the server. + LFI vulnerabilities can lead to the exposure of sensitive information, + such as configuration files, source code, or even data files, + which could be exploited to gain further access or to mount more + severe attacks. + + To mitigate this vulnerability, follow these steps: + - Avoid direct user input: If possible, do not use user input + to determine file paths. Use a mapping of user input to server-side + defined file paths instead. + - Use `File.basename`: If user input must be used to specify a file, + ensure that the input is normalized using `File.basename` to extract + the filename without any directory path. This prevents directory + traversal attacks. + - Path allow listing: Implement an allow list of permitted files or + directories and check user input against this list before processing. + + Secure Code Example: + ``` + def download + filename = params[:filename] + filepath = "path/to/secure/directory/#{File.basename(filename)}" + + # Optionally, further validate the resolved filepath against a whitelist + + if File.exist?(filepath) && !File.directory?(filepath) + send_file filepath, x_sendfile: true + else + render plain: "File not found", status: :not_found + end + end + ``` + languages: + - "ruby" + severity: "WARNING" + metadata: + owasp: + - "A5:2017-Broken Access Control" + - "A01:2021-Broken Access Control" + cwe: "CWE-73" + shortDescription: "External control of file name or path" + references: + - "https://owasp.org/www-community/attacks/Path_Traversal" + - "https://owasp.org/Top10/A01_2021-Broken_Access_Control/" + - "https://github.com/semgrep/semgrep-rules/blob/develop/ruby/rails/security/brakeman/check-send-file.yaml" + category: "security" + security-severity: "MEDIUM" + technology: + - "ruby" + - "rails" +- id: ruby_filter_rule-CheckBeforeFilter + mode: search + patterns: + - pattern-either: + - pattern: | + skip_filter ..., :except => $ARGS + - pattern: | + skip_before_filter ..., :except => $ARGS + message: | + The application was found disabling controller checks by setting `skip_filter` + or `skip_before_filter` with an `:except` option. This approach can + inadvertently open up parts of your application to unauthorized access + because it relies on a blocklist approach, where only specified actions + are protected. + + A safer method of providing this functionality involves specifying + exactly which controller actions should have checks applied using an + `:only` option, effectively creating an allowlist. This method ensures + that only specified actions are affected, and any new actions added to + the controller will have the filters applied by default, adhering to the + principle of secure by default. + + Secure Code Example: + ``` + class UsersController < ApplicationController + # Apply the filter only to these actions, making it clear and secure by default + skip_before_action :authenticate_user!, only: [:new, :create] + end + ``` + + In the secure example, `:authenticate_user!` filter is explicitly skipped + only for the `:new` and `:create actions`. This means any new action added + to the UsersController in the future will have the `authenticate_user!` + filter applied by default, ensuring that new parts of the application + are secure from the start. + languages: + - "ruby" + severity: "WARNING" + metadata: + owasp: + - "A5:2017-Broken Access Control" + - "A01:2021-Broken Access Control" + cwe: "CWE-749" + shortDescription: "Exposed dangerous method or function" + references: + - "https://owasp.org/Top10/A01_2021-Broken_Access_Control/" + - "https://github.com/semgrep/semgrep-rules/blob/develop/ruby/rails/security/brakeman/check-before-filter.yaml" + category: "security" + security-severity: "LOW" + technology: + - "ruby" + - "rails" +- id: ruby_find_rule-CheckUnscopedFind + mode: taint + pattern-sources: + - pattern-either: + - pattern: | + cookies[...] + - patterns: + - pattern: | + cookies. ... .$PROPERTY[...] + - metavariable-regex: + metavariable: $PROPERTY + regex: (?!signed|encrypted) + - pattern: | + params[...] + - pattern: | + request.env[...] + pattern-sinks: + - patterns: + - pattern-either: + - pattern: $MODEL.find(...) + - pattern: $MODEL.find_by_id(...) + - pattern: $MODEL.find_by_id!(...) + - metavariable-regex: + metavariable: $MODEL + regex: '[A-Z]\S+' + message: | + The application was found calling the `find(...)` method with user-controlled input. If the + ActiveRecord model being searched against is sensitive, this may lead to + Insecure Direct Object Reference (IDOR) behavior and allow users to read + arbitrary records. This could lead to data breaches, including the + exposure of personal information, account takeovers, and other security + issues. + + To mitigate this risk, it's essential to scope queries to the current + user or another appropriate scope that ensures users can only access + data they are authorized to see. This is done by using ActiveRecord + associations and scopes to limit the records that can be retrieved. + + Secure Code Example: + ``` + # Secure way to scope the find to the current user's accounts + def show + @account = current_user.accounts.find(params[:id]) + end + ``` + languages: + - "ruby" + severity: "WARNING" + metadata: + owasp: + - "A5:2017-Broken Access Control" + - "A01:2021-Broken Access Control" + cwe: "CWE-639" + shortDescription: "Authorization bypass through user-controlled key" + references: + - "https://brakemanscanner.org/docs/warning_types/unscoped_find/" + - "https://github.com/semgrep/semgrep-rules/blob/develop/ruby/rails/security/brakeman/check-unscoped-find.yaml" + category: "security" + security-severity: "MEDIUM" + technology: + - "ruby" + - "rails" +- id: ruby_ftp_rule-AvoidTaintedFTPCall + mode: taint + pattern-sources: + - pattern: params + - pattern: cookies + - pattern: request.env + pattern-sinks: + - pattern-either: + - pattern: Net::FTP.$X(...) + - patterns: + - pattern-inside: | + $FTP = Net::FTP.$OPEN(...) + ... + $FTP.$METHOD(...) + - pattern: $FTP.$METHOD(...) + message: | + The application was found calling the Net::FTP modules methods with + user supplied input. A malicious actor could use this to modify or access files + they should not have access to. + + Directly incorporating user-controlled input from `params`, `cookies`, + or `request.env` into FTP commands or connection setups can lead to + various security vulnerabilities, including Remote Code Execution + (RCE), unauthorized file access, and data exfiltration. It's crucial + to validate, sanitize, and, where possible, avoid using user-controlled + data in sensitive operations like FTP transactions. Ensure that any input + used in FTP operations is strictly controlled and validated against + expected patterns. + + Remediation Strategy: + To mitigate these risks, ensure that all user-provided input is strictly + validated and sanitized before being used in FTP operations. + - Verify the format and content of the input to ensure it meets expected + criteria. + - Use allowlists to restrict the input to known safe values. + - Employ built-in security features of the programming language or + framework to escape or safely handle user input. + + Secure Code Example: + ``` + filename = params[:filename] + # Validate the filename to ensure it's a known, safe file + raise "Invalid filename" unless filename =~ /\A[\w]+\.\w+\z/ + + Net::FTP.open('example.com', 'user', 'password') do |ftp| + # Proceed with the FTP operation using the validated and sanitized filename + ftp.getbinaryfile(filename, "local_#{filename}", 1024) + end + ``` + languages: + - "ruby" + severity: "WARNING" + metadata: + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + cwe: "CWE-76" + shortDescription: "Improper neutralization of equivalent special elements" + references: + - "https://github.com/semgrep/semgrep-rules/blob/develop/ruby/rails/security/audit/avoid-tainted-ftp-call.yaml" + category: "security" + security-severity: "MEDIUM" + technology: + - "ruby" + - "rails" +- id: ruby_http_rule-AvoidTaintedHTTPRequest + mode: taint + pattern-sources: + - pattern: params + - pattern: cookies + - pattern: request.env + pattern-sinks: + - pattern-either: + - patterns: + - pattern: Net::HTTP::$METHOD.new(...) + - metavariable-pattern: + metavariable: $METHOD + patterns: + - pattern-either: + - pattern: Copy + - pattern: Delete + - pattern: Get + - pattern: Head + - pattern: Lock + - pattern: Mkcol + - pattern: Move + - pattern: Options + - pattern: Patch + - pattern: Post + - pattern: Propfind + - pattern: Proppatch + - pattern: Put + - pattern: Trace + - pattern: Unlock + - patterns: + - pattern: Net::HTTP.$X(...) + - metavariable-pattern: + metavariable: $X + patterns: + - pattern-either: + - pattern: get + - pattern: get2 + - pattern: head + - pattern: head2 + - pattern: options + - pattern: patch + - pattern: post + - pattern: post2 + - pattern: post_form + - pattern: put + - pattern: request + - pattern: request_get + - pattern: request_head + - pattern: request_post + - pattern: send_request + - pattern: trace + - pattern: get_print + - pattern: get_response + - pattern: start + message: | + The application was found including unvalidated user input into `Net::HTTP` methods, + which could lead to HTTP Parameter Pollution (HPP) or worse, Server Side Request Forgery (SSRF). + Specifically, it looks for methods like GET, POST, DELETE, etc., + being called with parameters that could be controlled by an end-user. + Using untrusted input in such a manner without proper validation and + sanitization can lead to a variety of security vulnerabilities, including + SSRF, injection attacks, unintended data leaks, and unauthorized actions + being performed on behalf of the attacker. + + Ensure all user-controlled input is validated against a strict set of rules + (e.g., expected data types, patterns, and lengths) and sanitized to remove + or encode potentially harmful characters before being used in HTTP requests. + Additionally, consider using higher-level abstractions or frameworks that + automatically handle some of these concerns. + + Secure Code Example: + ``` + require 'uri' + + # Validate and sanitize the user input before using it in the HTTP request + begin + user_input = params[:url] + uri = URI.parse(user_input) + + # Ensure the URI is HTTP/HTTPS and refers to a trusted domain + if uri.scheme.match?(/\Ahttps?\z/) && uri.host == 'www.abc.com' + response = Net::HTTP.get(uri) + else + raise "Invalid URL" + end + rescue URI::InvalidURIError + puts "Provided URL is not valid" + end + ``` + languages: + - "ruby" + severity: "WARNING" + metadata: + category: "security" + shortDescription: "Server side request forgery (SSRF)" + cwe: "CWE-918" + owasp: + - "A1:2017-Injection" + - "A10:2021-Server-Side Request Forgery" + security-severity: "MEDIUM" + technology: + - "rails" + references: + - "https://github.com/semgrep/semgrep-rules/blob/develop/ruby/rails/security/audit/avoid-tainted-http-request.yaml" + + +- id: ruby_http_rule-CheckHTTPVerbConfusion + mode: search + patterns: + - pattern: | + if request.get? + ... + else + ... + end + - pattern-not-inside: | + if ... + elsif ... + ... + end + message: | + Found an improperly constructed control flow block with `request.get?`. + Rails will route HEAD requests as GET requests but they will fail the + `request.get?` check, potentially causing unexpected behavior unless an + `elsif` condition is used. + + Secure Code Example: + ``` + if request.get? + # Handle GET request logic here + elsif request.head? + # Handle HEAD request logic here + else + # Handle others if needed + end + ``` + languages: + - "ruby" + severity: "WARNING" + metadata: + category: "security" + shortDescription: "Improper check for unusual or exceptional conditions" + cwe: "CWE-754" + owasp: + - "A6:2017-Security Misconfiguration" + - "A04:2021-Insecure Design" + security-severity: "MEDIUM" + technology: + - "ruby" + - "rails" + references: + - "https://github.com/semgrep/semgrep-rules/blob/develop/ruby/rails/security/brakeman/check-http-verb-confusion.yaml" + + +- id: ruby_injection_rule-AvoidTaintedShellCall + mode: taint + pattern-sources: + - pattern-either: + - pattern: params[...] + - pattern: cookies + - pattern: request.env + pattern-sinks: + - patterns: + - pattern-either: + - patterns: + - pattern: Kernel.$X(...) + - patterns: + - pattern-either: + - pattern: Shell.$X(...) + - patterns: + - pattern-inside: | + $SHELL = Shell.$ANY(...) + ... + $SHELL.$X(...) + - pattern: $SHELL.$X(...) + - metavariable-pattern: + metavariable: $X + patterns: + - pattern-either: + - pattern: cat + - pattern: chdir + - pattern: chroot + - pattern: delete + - pattern: entries + - pattern: exec + - pattern: foreach + - pattern: glob + - pattern: install + - pattern: lchmod + - pattern: lchown + - pattern: link + - pattern: load + - pattern: load_file + - pattern: makedirs + - pattern: move + - pattern: new + - pattern: open + - pattern: read + - pattern: readlines + - pattern: rename + - pattern: rmdir + - pattern: safe_unlink + - pattern: symlink + - pattern: syscopy + - pattern: sysopen + - pattern: system + - pattern: truncate + - pattern: unlink + message: | + User input should never be used in constructing commands or command arguments + to functions which execute OS related functionality. Using external + input without validation in functions like `Kernel.system`, `exec`, or any + operations that interact with the shell or file system (`cat`, `delete` + etc.) poses a severe security risk. These patterns can lead to command + injection vulnerabilities, where an attacker could execute arbitrary + commands on the system the application is hosted on, leading to data + breaches, unauthorized access, or worse. + + To prevent command injection vulnerabilities, validate and sanitize all + user input before using it in any system or shell operation. Additionally, + consider using safer alternatives for executing system commands that don't + directly pass user input to the shell, such as parameterized APIs or + functions that handle arguments safely. + + Secure Code Example: + ``` + user_filename_key = params[:filename_key] + + allowed_filenames = { + 'file1' => 'allowed_file_1.txt', + 'file2' => 'allowed_file_2.txt', + } + + # Validate and select the filename from the lookup table + if allowed_filenames.has_key?(user_filename_key) + safe_filename = allowed_filenames[user_filename_key] + + # Use a safer API to read file content without invoking the shell + content = File.read(safe_filename) + else + puts "Invalid filename." + end + ``` + languages: + - "ruby" + severity: "ERROR" + metadata: + shortDescription: "Improper neutralization of special elements used in an OS command + ('OS Command Injection')" + category: "security" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + cwe: "CWE-78" + security-severity: "HIGH" + technology: + - "rails" + - "ruby" + references: + - "https://github.com/semgrep/semgrep-rules/blob/develop/ruby/rails/security/audit/avoid-tainted-shell-call.yaml" + +- id: ruby_injection_rule-BadSend + pattern-either: + - pattern: | + $PARAM = params[...] + ... + $RES = $MOD.send($PARAM.$FUNC) + - pattern: | + $PARAM = params[...] + ... + $RES = $MOD.try($PARAM.$FUNC) + - pattern: | + $PARAM = params[...] + ... + $RES = $MOD.__send__($PARAM.$FUNC) + - pattern: | + $PARAM = params[...] + ... + $RES = $MOD.public_send($PARAM.$FUNC) + message: | + The application was found calling dynamic method invocations in Ruby. + In particular one of the methods of: `Object#send`, `Object#try`, `Object#__send__`, + or `Object#public_send`. These methods are powerful Ruby features that allow + calling another method on an object + by name, where the method's name is passed as a string or symbol. + However, when combined with untrusted input, such as parameters from + web requests, they can lead to severe security vulnerabilities, including + arbitrary method execution and potentially arbitrary code execution. + + To mitigate these risks, it's crucial to validate and sanitize any user + input that might determine which methods are invoked. Moreover, consider + using safer alternatives to direct method invocation based on user input, + such as explicitly whitelisting allowed methods or using conditional logic + to determine method calls. + + Secure Code Example: + ``` + # Secure method invocation with validation and allow lists + method_name = params[:method].to_sym + allowed_methods = [:allowed_method_1, :allowed_method_2, :safe_method] + + if allowed_methods.include?(method_name) + result = object.public_send(method_name) + else + raise "Unauthorized method call" + end + ``` + languages: + - "ruby" + severity: "ERROR" + metadata: + shortDescription: "Improper control of generation of code ('Code Injection')" + category: "security" + cwe: "CWE-94" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "HIGH" + technology: + - "ruby" + references: + - "https://github.com/semgrep/semgrep-rules/blob/develop/ruby/lang/security/no-send.yaml" + - "https://the.igreque.info/posts/2016/01-object-send-considered-harmful-en.html" + + +- id: ruby_injection_rule-DangerousExec + mode: taint + pattern-sources: + - patterns: + - pattern: | + def $F(...,$ARG,...) + ... + end + - focus-metavariable: $ARG + - pattern: params + - pattern: cookies + pattern-sinks: + - patterns: + - pattern: | + $EXEC(...) + - pattern-not: | + $EXEC("...","...","...",...) + - pattern-not: | + $EXEC(["...","...","...",...],...) + - pattern-not: | + $EXEC({...},"...","...","...",...) + - pattern-not: | + $EXEC({...},["...","...","...",...],...) + - metavariable-regex: + metavariable: $EXEC + regex: ^(system|exec|spawn|Process.exec|Process.spawn|Open3.capture2|Open3.capture2e|Open3.capture3|Open3.popen2|Open3.popen2e|Open3.popen3|IO.popen|Gem::Util.popen|PTY.spawn)$ + message: | + OS command injection is a critical vulnerability that can lead to a full system + compromise as it may allow an adversary to pass in arbitrary commands or arguments + to be executed. + + User input should never be used in constructing commands or command arguments + to functions which execute OS commands. This includes filenames supplied by + user uploads or downloads. + + To mitigate this vulnerability, follow these best practices: + - Validate input: Ensure that all user inputs are validated against a + strict pattern that only allows safe characters for the context. Reject + any input that does not meet these criteria. + - Sanitize input: When validation is not feasible, sanitize the input + by escaping or removing potentially dangerous characters. + - Use secure methods: Prefer using secure methods or libraries designed + to execute system commands with parameters, which automatically handle + proper escaping of user inputs, such as `Open3.capture3` in Ruby. + - Least privilege: Run your application with the least privileges + necessary, limiting what an attacker can do if they manage to execute a + command. + + Secure Code Example: + Instead of directly interpolating user input into system commands, validate + user input against an allowlist, then use parameterized execution or safer + APIs like Open3: + ``` + require 'open3' + + user_input = params[:user_input] + # Define an allow list of permitted arguments + allowed_arguments = ['allowed_argument1', 'allowed_argument2', 'allowed_argument3'] + + # Validate user_input against the list + if allowed_arguments.include?(user_input) + # Using Open3 to safely execute system commands with allowed arguments + stdout, stderr, status = Open3.capture3('grep', user_input, 'my_file.txt') + if status.success? + puts stdout + else + warn "Error: #{stderr}" + end + else + warn "Error: Unpermitted argument." + end + ``` + languages: + - "ruby" + severity: "ERROR" + metadata: + shortDescription: "Improper control of generation of code ('Code Injection')" + category: "security" + cwe: "CWE-94" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "HIGH" + technology: + - "ruby" + - "rails" + references: + - "https://guides.rubyonrails.org/security.html#command-line-injection" + - "https://github.com/semgrep/semgrep-rules/blob/develop/ruby/lang/security/dangerous-exec.yaml" + +- id: ruby_mass_assignment_rule-ModelAttrAccessible + pattern-either: + - pattern: | + ....permit(..., :admin, ...) + - pattern: | + ....permit(..., :role, ...) + - pattern: | + ....permit(..., :banned, ...) + - pattern: | + ....permit(..., :account_id, ...) + - pattern: | + attr_accessible ..., :admin, ... + - pattern: | + attr_accessible ..., :role, ... + - pattern: | + attr_accessible ..., :banned, ... + - pattern: | + attr_accessible ..., :account_id, ... + - pattern: | + params.permit! + message: | + The application was found permitting attributes which could lead to mass assignment + vulnerabilities. Permitting attributes such as `admin`, `role`, `banned` etc, + without proper authorization checks can lead to security issues like unauthorized + access or privilege escalation. + + Remediation Strategy + - Explicitly permit attributes: Carefully review which attributes are + permissible and avoid including sensitive ones in the list. + - Role-based permissions: Implement checks that allow only authorized + users (e.g., administrators) to modify sensitive attributes. + - Avoid using `params.permit!`: Use specific permit statements instead of + permitting all parameters to ensure only expected attributes are allowed + for mass assignment. + + Secure Code Example: + ``` + # Secure: Conditionally permit sensitive attributes based on user role + def user_params + permitted = params.require(:user).permit(:name, :email) + permitted[:role] = params[:user][:role] if current_user.admin? && params[:user][:role].present? + permitted + end + + def user_params2 + permitted_attributes = [:username, :email] + # Only allow 'admin' attribute to be updated by users with admin role + permitted_attributes << :admin if current_user.admin? + params.require(:user).permit(*permitted_attributes) + end + ``` + languages: + - "ruby" + severity: "WARNING" + metadata: + category: "security" + shortDescription: "Improperly controlled modification of dynamically-determined object attributes" + cwe: "CWE-915" + owasp: + - "A6:2017-Security Misconfiguration" + - "A08:2021-Software and Data Integrity Failures" + security-severity: "MEDIUM" + technology: + - "ruby" + - "rails" + references: + - "https://cheatsheetseries.owasp.org/cheatsheets/Mass_Assignment_Cheat_Sheet.html" + - "https://github.com/semgrep/semgrep-rules/blob/develop/ruby/lang/security/model-attr-accessible.yaml" +- id: ruby_mass_assignment_rule-UnprotectedMassAssign + patterns: + - pattern-either: + - pattern: | + $MOD.new(params[$CODE]) + - pattern: | + $MOD.new(..., params[$CODE], :without_protection => true, ...) + - pattern-not-inside: | + attr_accessible $VAR + ... + $MOD.new(params[$CODE]) + message: | + Checks for calls to `without_protection` during mass assignment (which + allows record creation from hash values). This can lead to users bypassing + permissions protections. Using `:without_protection => true` makes your + application vulnerable to attackers who may craft malicious requests to + modify sensitive attributes, leading to unauthorized access or data + manipulation. For Rails 4 and higher, mass protection is on by default. + + To mitigate this issue, don't use :without_protection => true. Instead, + configure attr_accessible to control attribute access. + + Secure Code Example: + ``` + class User < ActiveRecord::Base + # Only name and email can be updated via mass assignment + attr_accessible :name, :email + + # admin and account_id are not listed here, so they cannot be mass-assigned + end + ``` + languages: + - "ruby" + severity: "WARNING" + metadata: + category: "security" + shortDescription: "Improperly controlled modification of dynamically-determined object attributes" + cwe: "CWE-915" + owasp: + - "A6:2017-Security Misconfiguration" + - "A08:2021-Software and Data Integrity Failures" + security-severity: "MEDIUM" + technology: + - "ruby" + - "rails" + references: + - "https://cheatsheetseries.owasp.org/cheatsheets/Mass_Assignment_Cheat_Sheet.html" + - "https://github.com/semgrep/semgrep-rules/blob/develop/ruby/lang/security/unprotected-mass-assign.yaml" +- id: ruby_redirect_rule-CheckRedirectTo + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - pattern: params + - pattern: cookies + - pattern: request.env + - pattern: url_for(params[...],...,:only_path => false,...) + pattern-sanitizers: + - patterns: + - pattern-either: + - patterns: + - pattern: | + $F(...) + - metavariable-pattern: + metavariable: $F + patterns: + - pattern-not-regex: (params|url_for|cookies|request.env|permit|redirect_to) + - pattern: | + params.merge! :only_path => true + ... + - pattern: | + params.slice(...) + ... + - pattern: | + redirect_to [...] + - patterns: + - pattern: | + $MODEL. ... .$M(...) + ... + - metavariable-regex: + metavariable: $MODEL + regex: '[A-Z]\w+' + - metavariable-regex: + metavariable: $M + regex: (all|create|find|find_by|find_by_sql|first|last|new|from|group|having|joins|lock|order|reorder|select|where|take) + - patterns: + - pattern: | + params.$UNSAFE_HASH.merge(...,:only_path => true,...) + ... + - metavariable-regex: + metavariable: $UNSAFE_HASH + regex: to_unsafe_h(ash)? + - patterns: + - pattern: params.permit(...,$X,...) + - metavariable-pattern: + metavariable: $X + patterns: + - pattern-not-regex: (host|port|(sub)?domain) + pattern-sinks: + - patterns: + - pattern: $X + - pattern-inside: | + redirect_to $X, ... + - pattern-not-regex: params\.\w+(? true` + hash value. Using `:only_path => true` ensures that the URL is interpreted + as a relative path, not allowing redirection to an arbitrary external URL, + thus mitigating the risk of open redirects. Alternatively, validate or + sanitize the input to ensure it's safe and intended. + + Secure Code Example: + ``` + # Secure - Ensuring redirection is only to internal paths + def secure_redirect + redirect_to params[:redirect_url], only_path: true + end + ``` + languages: + - "ruby" + severity: "INFO" + metadata: + shortDescription: "URL redirection to untrusted site 'open redirect'" + category: "security" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + cwe: "CWE-601" + security-severity: "LOW" + technology: + - "ruby" + - "rails" + references: + - "https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html" + - "https://github.com/semgrep/semgrep-rules/blob/develop/ruby/rails/security/brakeman/check-redirect-to.yaml" +- id: ruby_reflection_rule-CheckUnsafeReflection + mode: taint + pattern-sources: + - pattern-either: + - pattern: | + cookies[...] + - patterns: + - pattern: | + cookies. ... .$PROPERTY[...] + - metavariable-regex: + metavariable: $PROPERTY + regex: (?!signed|encrypted) + - pattern: | + params[...] + - pattern: | + request.env[...] + pattern-sinks: + - patterns: + - pattern: $X + - pattern-either: + - pattern-inside: | + $X.constantize + - pattern-inside: | + $X. ... .safe_constantize + - pattern-inside: | + const_get(...) + - pattern-inside: | + qualified_const_get(...) + message: | + The application was found calling a reflection method with user-controllable + input. Reflection in Ruby allows a program to examine and modify its own + structure and behavior at runtime. When user input is used unsafely + with reflection methods (like `constantize`, `safe_constantize`, `const_get`, + `qualified_const_get`), it poses a significant security risk, potentially + leading to arbitrary code execution. + + To mitigate these risks: + - Avoid direct user input in reflection: Never use user-controllable input + directly with reflection methods. + - Validate and sanitize input: If user input must influence program behavior, + rigorously validate and sanitize the input against a whitelist of allowed + values. + - Use indirect references: Instead of allowing direct specification of class + or method names, map user inputs to a predefined set of allowed actions or + classes. + - Do not provide user-controllable input to reflection functionality. + - Do not call symbol conversion on user-controllable input. + + Secure Code Example: + ``` + class SafeClassHandler + ALLOWED_CLASSES = { + 'user' => User, + 'product' => Product + }.freeze + + def self.handle_class_action(class_key) + klass = ALLOWED_CLASSES[class_key] + raise ArgumentError, "Invalid class key" unless klass + + klass.some_method + end + end + + # Example usage + SafeClassHandler.handle_class_action(params[:class_key]) + ``` + languages: + - "ruby" + severity: "ERROR" + metadata: + shortDescription: "Improper control of generation of code ('Code Injection')" + category: "security" + cwe: "CWE-94" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "HIGH" + technology: + - "ruby" + - "rails" + references: + - "https://github.com/semgrep/semgrep-rules/blob/develop/ruby/rails/security/brakeman/check-unsafe-reflection.yaml" +- id: ruby_reflection_rule-CheckUnsafeReflectionMethods + mode: taint + pattern-sources: + - pattern-either: + - pattern: | + cookies[...] + - patterns: + - pattern: | + cookies. ... .$PROPERTY[...] + - metavariable-regex: + metavariable: $PROPERTY + regex: (?!signed|encrypted) + - pattern: | + params[...] + - pattern: | + request.env[...] + pattern-sinks: + - patterns: + - pattern: $X + - pattern-either: + - pattern-inside: | + $X. ... .to_proc + - patterns: + - pattern-inside: | + $Y.method($Z) + - focus-metavariable: $Z + - patterns: + - pattern-inside: | + $Y.tap($Z) + - focus-metavariable: $Z + - patterns: + - pattern-inside: | + $Y.tap{ |$ANY| $Z } + - focus-metavariable: $Z + message: | + The application was found calling a reflection method with user-controllable + input. This practice can lead to unauthorized alteration of program behavior, + including the potential execution of arbitrary code. Reflection methods + allow dynamic execution of code, which is powerful but risky if not properly + sanitized, as it could enable attackers to execute unintended methods or + blocks. + + Remediation: + - Validate and sanitize input: Ensure that any user input is strictly + validated against a whitelist of allowed values before being passed to + reflection methods. Avoid direct mapping of user input to method names + or proc conversions. + - Limit reflection use: Minimize the use of reflection with user input. + Prefer direct method calls or other non-reflective approaches whenever + possible. + - Use safer alternatives: When dynamic behavior is necessary, use controlled + methods like `public_send` with proper input validation to reduce risk. + + Secure Code Example: + ``` + # Assume user input is to invoke a method on an object + user_method = params[:method_name] + + # Define an allow list of permissible methods + allowed_methods = ['safe_method_1', 'safe_method_2'] + + if allowed_methods.include?(user_method) + # Using public_send for controlled method invocation + result = my_object.public_send(user_method) + else + raise 'Unauthorized method access' + end + ``` + languages: + - "ruby" + severity: "ERROR" + metadata: + shortDescription: "Improper control of generation of code ('Code Injection')" + category: "security" + cwe: "CWE-94" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "HIGH" + technology: + - "ruby" + - "rails" + references: + - "https://github.com/semgrep/semgrep-rules/blob/develop/ruby/rails/security/brakeman/check-unsafe-reflection-methods.yaml" +- id: ruby_regex_rule-CheckRegexDOS + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - pattern: | + cookies[...] + - patterns: + - pattern: | + cookies. ... .$PROPERTY[...] + - metavariable-regex: + metavariable: $PROPERTY + regex: (?!signed|encrypted) + - pattern: | + params[...] + - pattern: | + request.env[...] + - patterns: + - pattern: $Y + - pattern-either: + - pattern-inside: | + $RECORD.read_attribute($Y) + - pattern-inside: | + $RECORD[$Y] + - metavariable-regex: + metavariable: $RECORD + regex: '[A-Z][a-z]+' + pattern-sinks: + - patterns: + - pattern-either: + - patterns: + - pattern: $Y + - pattern-inside: | + /...#{...}.../ + - patterns: + - pattern: $Y + - pattern-inside: | + Regexp.new(...) + message: | + The application was found constructing a regular expression with user-controllable + input. This may result in excessive resource consumption + when applied to certain inputs, or when the user is allowed to control + the match target. + + To mitigate the issue, avoid allowing users to specify regular expressions + processed by the server. If you must support user-controllable input in a + regular expression, use an allow-list to restrict the expressions users + may supply to limit catastrophic backtracking. + + Secure Code Example: + ``` + # Define an allow-list of safe, predefined patterns + ALLOWED_PATTERNS = { + 'digits_only' => /^\d+$/, + 'letters_only' => /^[a-zA-Z]+$/, + 'email_format' => /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/ + } + user_pattern_key = params[:pattern_key] + target_data = params[:data] + + if ALLOWED_PATTERNS.key?(user_pattern_key) + # Fetch the safe pattern from the allow-list + safe_pattern = ALLOWED_PATTERNS[user_pattern_key] + + # Apply the regular expression safely + if target_data.match(safe_pattern) + # Do something + else + # Do something + end + else + # Handle case where the pattern is not allowed + end + ``` + languages: + - "ruby" + severity: "WARNING" + metadata: + category: "security" + cwe: "CWE-1333" + shortDescription: "Inefficient regular expression complexity" + owasp: + - "A6:2017-Security Misconfiguration" + - "A04:2021-Insecure Design" + security-severity: "MEDIUM" + technology: + - "ruby" + - "rails" + references: + - "https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS" + - "https://github.com/semgrep/semgrep-rules/blob/develop/ruby/rails/security/brakeman/check-regex-dos.yaml" +- id: ruby_regex_rule-CheckValidationRegex + mode: search + patterns: + - pattern-either: + - pattern: | + validates ..., :format => <... $V ...>,... + - pattern: | + validates_format_of ..., :with => <... $V ...>,... + - metavariable-regex: + metavariable: $V + regex: /(.{2}(? ...`. + + Ruby regex behavior is multiline by default and lines should be terminated + by `\A` for beginning of line and `\Z` for end of line, respectively. + + Secure Code Example: + ``` + class User < ApplicationRecord + # Securely anchored from start to end of the string + validates :username, format: { with: /\A(?=.*[a-zA-Z])[a-zA-Z0-9]+\z/ } + end + ``` + languages: + - "ruby" + severity: "WARNING" + metadata: + category: "security" + cwe: "CWE-185" + shortDescription: "Incorrect regular expression" + owasp: + - "A5:2017-Broken Access Control" + - "A01:2021-Broken Access Control" + security-severity: "MEDIUM" + technology: + - "ruby" + - "rails" + references: + - "https://brakemanscanner.org/docs/warning_types/format_validation/" + - "https://github.com/semgrep/semgrep-rules/blob/develop/ruby/rails/security/brakeman/check-validation-regex.yaml" +- id: ruby_routes_rule-AvoidDefaultRoutes + patterns: + - pattern-either: + - pattern: map.connect ":controller/:action/:id" + - pattern: match ':controller(/:action(/:id(.:format)))' + paths: + include: + - '*routes.rb' + message: | + Default routes are enabled in this routes file. This means any public method on a + controller can be called as an action. It is easy to accidentally expose + methods. Instead, remove the offending line and explicitly include all + routes that are intended for external users to follow. + + Secure Code Example: + ``` + # In routes.rb + Rails.application.routes.draw do + get 'posts' => 'posts#index', as: :posts + get 'posts/:id' => 'posts#show', as: :post + post 'posts' => 'posts#create' + + # Other CRUD actions for posts can be defined similarly + end + ``` + languages: + - "ruby" + severity: "WARNING" + metadata: + owasp: + - "A5:2017-Broken Access Control" + - "A01:2021-Broken Access Control" + cwe: "CWE-276" + shortDescription: "Incorrect Default Permissions" + security-severity: "MEDIUM" + references: + - "https://github.com/semgrep/semgrep-rules/blob/develop/ruby/rails/security/audit/xss/avoid-default-routes.yaml" + category: "security" + technology: + - "rails" + +- id: ruby_session_rule-AvoidSessionManipulation + mode: taint + pattern-sources: + - pattern: params + - pattern: cookies + - pattern: request.env + pattern-sinks: + - pattern: session[...] + message: | + The application was found retrieving session data using user input. A + malicious user may be able to retrieve information from the session + that was not meant to be allowed. + Session manipulation can occur when an application allows user-input in + session keys. Since sessions are typically considered a source of truth + (e.g. to check the logged-in user or to match CSRF tokens), allowing an + attacker to manipulate the session may lead to unintended behavior. + + To mitigate this issue, never use user input as a session key. Instead, + consider an allow list approach to control access to session keys, + ensuring only predefined keys are accessible, and user input is not used + to directly access the session key values. + + Secure Code Example: + ``` + # Define an allowed list of permitted session keys + ALLOWED_SESSION_KEYS = ['display_settings', 'locale'] + + user_provided_key = params[:key] + + # Validate the key against the list + if ALLOWED_SESSION_KEYS.include?(user_provided_key) + # Access the session value safely + value = session[user_provided_key] + else + raise "Invalid session key provided." + end + ``` + languages: + - "ruby" + severity: "ERROR" + metadata: + shortDescription: "Incorrect default permissions" + owasp: + - "A5:2017-Broken Access Control" + - "A01:2021-Broken Access Control" + cwe: "CWE-276" + security-severity: "CRITICAL" + references: + - "https://brakemanscanner.org/docs/warning_types/session_manipulation/" + - "https://github.com/semgrep/semgrep-rules/blob/develop/ruby/rails/security/audit/avoid-session-manipulation.yaml" + category: "security" + technology: + - "rails" + +- id: ruby_sql_rule-CheckSQL + mode: taint + pattern-sources: + - pattern-either: + - pattern: | + cookies[...] + - patterns: + - pattern: | + cookies. ... .$PROPERTY[...] + - metavariable-regex: + metavariable: $PROPERTY + regex: (?!signed|encrypted) + - pattern: | + params[...] + - pattern: | + request.env[...] + pattern-sanitizers: + - patterns: + - pattern-either: + - patterns: + - pattern: $X + - pattern-either: + - pattern-inside: | + :$KEY => $X + - pattern-inside: | + ["...",$X,...] + - pattern: | + params[...].to_i + - pattern: | + params[...].to_f + - patterns: + - pattern: | + params[...] ? $A : $B + - metavariable-pattern: + metavariable: $A + patterns: + - pattern-not: | + params[...] + - metavariable-pattern: + metavariable: $B + patterns: + - pattern-not: | + params[...] + pattern-sinks: + - patterns: + - pattern: $X + - pattern-not-inside: | + $P.where("...",...) + - pattern-not-inside: | + $P.where(:$KEY => $VAL,...) + - pattern-either: + - pattern-inside: | + $P.$M(...) + - pattern-inside: | + $P.$M("...",...) + - pattern-inside: | + class $P < ActiveRecord::Base + ... + end + - metavariable-regex: + metavariable: $M + regex: (where|find|first|last|select|minimum|maximum|calculate|sum|average) + message: | + SQL Injection is a critical vulnerability that can lead to data or system compromise. By + dynamically generating SQL query strings, user input may be able to influence the logic of + the SQL statement. This could lead to an adversary accessing information they should + not have access to, or in some circumstances, being able to execute OS functionality or code. + + To mitigate this issue, always use parameterized queries or the + ActiveRecord query interface, which ensures that inputs are properly + escaped, preventing SQL injection attacks. Avoid string interpolation + or concatenation with user-controlled input for constructing SQL queries. + + Secure Code Example: + ``` + # Secure: Using parameterized queries with ActiveRecord + user_id = params[:id] + User.where("id = ?", user_id) + + # Secure: Using ActiveRecord's query methods, which automatically handle parameterization + # Converting to integer as an additional layer of input sanitization + user_id = params[:id].to_i + User.where(id: user_id) + ``` + languages: + - "ruby" + severity: "ERROR" + metadata: + shortDescription: "Improper neutralization of special elements used in a SQL + command ('SQL Injection')" + category: "security" + cwe: "CWE-89" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "HIGH" + technology: + - "ruby" + - "rails" + references: + - "https://owasp.org/www-community/attacks/SQL_Injection" + - "https://github.com/semgrep/semgrep-rules/blob/develop/ruby/rails/security/brakeman/check-sql.yaml" +- id: ruby_ssl_rule-ForceSSLFalse + pattern: config.force_ssl = false + fix-regex: + regex: =\s*false + replacement: = true + message: | + The application was found setting `force_ssl` to `false`. This setting + can expose the application to the risk of network + interception of unencrypted traffic. Enabling `force_ssl` by setting + `config.force_ssl = true` in the application's configuration, specifically + within `config/environments/production.rb`, forces the use of HTTPS, + encrypting data in transit and safeguarding against eavesdropping or data + tampering. + languages: + - "ruby" + severity: "WARNING" + metadata: + cwe: "CWE-319" + shortDescription: "Cleartext transmission of sensitive information" + category: "security" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A04:2021-Insecure Design" + security-severity: "MEDIUM" + technology: + - "ruby" + references: + - "https://github.com/semgrep/semgrep-rules/blob/develop/ruby/lang/security/force-ssl-false.yaml" + + +- id: ruby_ssl_rule-SSLModeNoVerify + pattern: OpenSSL::SSL::VERIFY_NONE + fix-regex: + regex: VERIFY_NONE + replacement: VERIFY_PEER + message: | + The application was found using `OpenSSL::SSL::VERIFY_NONE`. + This effectively disables the validation of TLS certificates. + + This allows for an adversary who is in between the application and the + target host to intercept potentially sensitive information or transmit + malicious data. + + To remediate this issue, use 'OpenSSL::SSL::VERIFY_PEER' instead. + severity: "WARNING" + languages: + - "ruby" + metadata: + cwe: "CWE-295" + shortDescription: "Improper certificate validation" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A07:2021-Identification and Authentication Failures" + category: "security" + security-severity: "MEDIUM" + technology: + - "ruby" + references: + - "https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures" + - "https://github.com/semgrep/semgrep-rules/blob/develop/ruby/lang/security/ssl-mode-no-verify.yaml" +- id: ruby_xss_rule-AvoidLinkTo + mode: taint + pattern-sources: + - pattern: params + - pattern: cookies + - pattern: request.env + - pattern-either: + - pattern: $MODEL.url(...) + - pattern: $MODEL.uri(...) + - pattern: $MODEL.link(...) + - pattern: $MODEL.page(...) + - pattern: $MODEL.site(...) + pattern-sinks: + - pattern: link_to(...) + pattern-sanitizers: + - patterns: + - pattern: | + "...#{...}..." + - pattern-not: | + "#{...}..." + message: | + This code includes user input in `link_to`. In Rails, the body of + `link_to` is not escaped. This means that user input which reaches the + body will be executed when the HTML is rendered. Even in other versions, + values starting with `javascript:` or `data:` are not escaped. + + Mitigation Strategy: + Always sanitize user input used within `link_to` method calls. For versions of + Rails where `link_to` does not automatically escape the body, or when dealing + with schemes that are not escaped (`javascript:`, `data:`), manually escape or + validate the input against a list of safe values. Consider using the `sanitize` + helper method or other Rails sanitization helpers to clean user input before + rendering. + + Secure Code Example: + ``` + user_input = params[:user_link_text] + + # This example uses the `sanitize` helper to ensure any HTML tags or JavaScript in the user input are escaped + safe_link_text = sanitize(user_input) + + # Use the sanitized text as the body of the `link_to` method + <%= link_to safe_link_text, some_safe_path %> + ``` + languages: + - "ruby" + severity: "WARNING" + metadata: + shortDescription: "Improper neutralization of input during web page generation + ('Cross-site Scripting')" + category: "security" + cwe: "CWE-79" + owasp: + - "A7:2017-Cross-Site Scripting (XSS)" + - "A03:2021-Injection" + security-severity: "MEDIUM" + technology: + - "rails" + references: + - "https://brakemanscanner.org/docs/warning_types/link_to/" + - "https://brakemanscanner.org/docs/warning_types/link_to_href/" + - "https://github.com/semgrep/semgrep-rules/blob/develop/ruby/rails/security/audit/xss/avoid-link-to.yaml" + + +- id: ruby_xss_rule-AvoidRenderInline + pattern: 'render inline: ...' + message: | + The application was found calling `render inline: ...` which renders an entire ERB template inline and is potentially dangerous. + If user supplied input is used, the application can be exploited by malicious + actors via server-side template injection (SSTI) or cross-site scripting (XSS) attacks. + Instead, consider using a partial or another safe rendering method. + + Secure Code Example: + ``` + # In your controller or view + user_input = params[:user_input] + render partial: 'users/user_input', locals: { user_input: user_input } + + # erb file + + +
    + <%= sanitize(user_input) %> +
    + ``` + languages: + - "ruby" + severity: "WARNING" + metadata: + shortDescription: "Improper neutralization of input during web page generation + ('Cross-site Scripting')" + category: "security" + cwe: "CWE-79" + owasp: + - "A7:2017-Cross-Site Scripting (XSS)" + - "A03:2021-Injection" + security-severity: "MEDIUM" + technology: + - "rails" + references: + - "https://brakemanpro.com/2017/09/08/cross-site-scripting-in-rails#inline-renders---even-worse-than-xss" + - "https://github.com/semgrep/semgrep-rules/blob/develop/ruby/rails/security/audit/xss/avoid-render-inline.yaml" + + + +- id: ruby_xss_rule-AvoidRenderText + pattern: 'render text: ...' + fix-regex: + regex: 'text:' + replacement: 'plain:' + message: | + The application was found calling `render text: ...` which actually sets the + content-type to 'text/html'. If external data can reach here, this exposes your + application to cross-site scripting (XSS) attacks. Instead, use `render plain: ...` to + render non-HTML text. + languages: + - "ruby" + severity: "WARNING" + metadata: + shortDescription: "Improper neutralization of input during web page generation + ('Cross-site Scripting')" + category: "security" + cwe: "CWE-79" + owasp: + - "A7:2017-Cross-Site Scripting (XSS)" + - "A03:2021-Injection" + security-severity: "MEDIUM" + technology: + - "rails" + references: + - "https://brakemanpro.com/2017/09/08/cross-site-scripting-in-rails#inline-renders---even-worse-than-xss" + - "https://github.com/semgrep/semgrep-rules/blob/develop/ruby/rails/security/audit/xss/avoid-render-text.yaml" + + + + +- id: ruby_xss_rule-ManualTemplateCreation + pattern: ERB.new(...) + message: | + The application was identified manually creating ERB templates. Manual creation of templates + may expose your application to server-side template injection (SSTI) or + cross-site scripting (XSS) attacks if user input is used to create the + template. Instead, create a '.erb' template file and use 'render'. + + Secure Code Example: + ``` + # Controller: messages_controller.rb + class MessagesController < ApplicationController + def show + # Safely assign user input to an instance variable + @message_content = sanitize(params[:user_content]) + + # Render the static .erb template + render 'messages/show' + end + end + + +
    + Message: <%= @message_content %> +
    + ``` + languages: + - "ruby" + severity: "WARNING" + metadata: + shortDescription: "Improper neutralization of input during web page generation + ('Cross-site Scripting')" + category: "security" + cwe: "CWE-79" + owasp: + - "A7:2017-Cross-Site Scripting (XSS)" + - "A03:2021-Injection" + security-severity: "MEDIUM" + technology: + - "rails" + references: + - "https://github.com/semgrep/semgrep-rules/blob/develop/ruby/rails/security/audit/xss/manual-template-creation.yaml" + + + + +- id: yaml_spring_rule-SpringActuatorFullyEnabled + languages: + - "yaml" + severity: "WARNING" + message: | + Spring Boot Actuator is fully enabled. This exposes sensitive endpoints + such as /actuator/env, /actuator/logfile, /actuator/heapdump and others. + If the application lacks proper security measures (e.g., authentication and + authorization), sensitive data could be accessed, compromising the application and + its infrastructure. This configuration poses a serious risk in production + environments or public-facing deployments. + + To mitigate the risks, take the following measures: + - Expose only the Actuator endpoints required for your use case + - For production environments, restrict exposure to non-sensitive endpoints + like `health` or `info` + - Ensure Actuator endpoints are protected with authentication and authorization + (e.g., via Spring Security) + - Use environment-specific configurations to limit exposure in production + + Secure Code Example: + Instead of include: "*", list only the endpoints you need to expose: + ``` + management: + endpoints: + web: + exposure: + include: "health,info,metrics" + ``` + + References: + - https://docs.spring.io/spring-boot/reference/actuator/endpoints.html#actuator.endpoints.exposing + - https://medium.com/walmartglobaltech/perils-of-spring-boot-actuators-misconfiguration-185c43a0f785 + - https://blog.maass.xyz/spring-actuator-security-part-1-stealing-secrets-using-spring-actuators + metadata: + likelihood: MEDIUM + impact: HIGH + confidence: MEDIUM + shortDescription: "Exposure of sensitive system information to an unauthorized control sphere" + category: "security" + cwe: "CWE-497" + owasp: + - "A01:2021-Broken Access Control" + - "A3:2017-Sensitive Data Exposure" + security-severity: "Medium" + technology: + - "java" + patterns: + - pattern: | + management: + ... + endpoints: + ... + web: + ... + exposure: + ... + include: "*" + ... +- id: rules_lgpl_java_webview_rule-ignore-ssl-certificate-errors + pattern: > + $RET onReceivedSslError(WebView $W, SslErrorHandler $H, SslError + $E) { + ... + $H.proceed(); + } + message: | + Insecure WebView Implementation. leading to a security problem known as SSL certificate + validation bypass. This occurs when the app fails to properly validate SSL certificates, + allowing potentially malicious or spoofed certificates to be accepted, leading to a + Man-in-the-Middle (MitM) attack where an attacker intercepts and manipulates communication + between the app and the server. + + To fix this security issue, you should properly handle SSL errors and only proceed with + the connection if the SSL certificate is valid and trusted. Here's an example code in Java: + ``` + public class MyWebViewClient extends WebViewClient { + @Override + public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) { + // Check the SSL error type + switch (error.getPrimaryError()) { + case SslError.SSL_UNTRUSTED: + // Certificate is untrusted + // Handle the error appropriately, such as showing an error message + break; + case SslError.SSL_EXPIRED: + // Certificate has expired + // Handle the error appropriately + break; + case SslError.SSL_IDMISMATCH: + // Certificate hostname mismatch + // Handle the error appropriately + break; + case SslError.SSL_NOTYETVALID: + // Certificate is not yet valid + // Handle the error appropriately + break; + } + // Cancel the connection + // This prevents the WebView from loading the content + handler.cancel(); + } + } + ``` + languages: + - java + severity: WARNING + metadata: + category: security + cwe: "CWE-295" + shortDescription: Improper certificate validation" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + security-severity: MEDIUM +- id: rules_lgpl_java_webview_rule-webview-debugging + patterns: + - pattern-either: + - pattern: | + $WB.setWebContentsDebuggingEnabled(true); + - pattern: | + $X = true; + ... + $WB.setWebContentsDebuggingEnabled($X); + message: | + Remote WebView debugging is enabled. This allows an attacker with + debugging access to interact with the webview and steal or corrupt data. + To fix these security issues, it is recommended to disable remote + debugging and restrict file access in the WebView. + Here's how you can do it: + ``` + WebView webView = new WebView(context); + + // Disable remote debugging + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + WebView.setWebContentsDebuggingEnabled(false); + } + + // Restrict file access from file URLs + webView.getSettings().setAllowFileAccessFromFileURLs(false); + + // Load a web page + webView.loadUrl("https://example.com"); + ``` + languages: + - java + severity: WARNING + metadata: + category: security + cwe: "CWE-489" + shortDescription: "Active debug code" + owasp: + - "A6:2017-Security Misconfiguration" + - "A05:2021-Security Misconfiguration" + security-severity: MEDIUM +- id: rules_lgpl_java_webview_rule-webview-external-storage + patterns: + - pattern-either: + - pattern: | + $X = <... $E.getExternalStorageDirectory() ...>; + ... + $WV.loadUrl(<... $X ...>); + - pattern: | + $WV.loadUrl(<... $E.getExternalStorageDirectory().$F() ...>); + - pattern: | + $X = <... Environment.getExternalStorageDirectory().$F() ...>; + ... + $WV.loadUrl(<... $X ...>); + - pattern: | + $X = <... $E.getExternalFilesDir(...) ...>; + ... + $WV.loadUrl(<... $X ...>); + message: | + WebView load files from external storage. Files in external storage can be + modified by any application. + + Loading files from external storage in a WebView can introduce security risks, + as it allows web content to access potentially sensitive data stored on the + device's external storage. This can lead to unauthorized access to user data, + including personal files, credentials, or other sensitive information, by + malicious web content. + + To fix this security issue, you should avoid loading files directly from external + storage in a WebView. Instead, you should use a Content Provider or a secure file + storage mechanism to access files and provide them to the WebView as content. + + Here's a general approach to fix this problem: + (1) Use a Content Provider: If you need to load files from external storage in a WebView, + consider using a Content Provider to securely access the files. Content Providers + provide controlled access to files stored on external storage and allow you to define + permissions for accessing them. + (2) Secure File Storage: Store files containing sensitive data in a secure location, such + as internal storage or encrypted storage, and provide access to them through a secure + API. Avoid exposing sensitive files directly to the WebView. + (3) Restrict WebView Access: Configure the WebView to restrict access to external resources + and content. Use methods like setAllowFileAccess() to control file access and + setAllowContentAccess() to control access to content from other origins. + Here's an example of how you can use a Content Provider to provide secure access to + files in a WebView: + ``` + // Define the URI of the content provider for accessing files + Uri contentProviderUri = Uri.parse("content://com.example.myapp.provider/files"); + // Load the content from the Content Provider into the WebView + webView.loadUrl(contentProviderUri.toString()); + ``` + In the above code, we define the URI of a Content Provider that provides access to files + stored in the app's external storage. The content is loaded from the Content Provider into + the WebView using loadUrl(), which ensures that access to files is controlled and secure, + preventing unauthorized access to sensitive data. + languages: + - java + severity: ERROR + metadata: + category: security + cwe: "CWE-749" + shortDescription: "Exposed dangerous method or function" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: CRITICAL +- id: rules_lgpl_java_webview_rule-webview-set-allow-file-access + pattern: $WB.setAllowFileAccess(true); + message: | + WebView File System Access is enabled. An attacker able to inject + script into a WebView, could exploit the opportunity to unauthorized + access to sensitive user data or system files. + + To fix this security issue, you should disable file access in the + WebView or restrict it to specific directories. + An example: + ``` + // Create a WebView instance + WebView webView = new WebView(context); + // Disable file access in the WebView + webView.getSettings().setAllowFileAccess(false); + ``` + languages: + - java + severity: WARNING + metadata: + category: security + cwe: "CWE-73" + shortDescription: "External control of file name or path" + owasp: + - "A5:2017-Broken Access Control" + - "A01:2021-Broken Access Control" + security-severity: MEDIUM +- id: rules_lgpl_javascript_crypto_rule-node-aes-ecb + patterns: + - pattern-either: + - pattern: | + $X.createCipheriv("=~/^aes-([0-9]+)-ecb$/i", ...) + - pattern: | + $X.createDecipheriv("=~/^aes-([0-9]+)-ecb$/i", ...) + message: | + AES with ECB mode is deterministic in nature and not suitable for encrypting large amount of repetitive data. + languages: + - "javascript" + severity: "WARNING" + metadata: + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + cwe: "CWE-327" + shortDescription: "Use of a broken or risky cryptographic algorithm" + security-severity: "MEDIUM" + category: "security" +- id: rules_lgpl_javascript_crypto_rule-node-aes-noiv + patterns: + - pattern-either: + - pattern: | + $X.createCipheriv("=~/^aes-/i", $KEY, "", ...) + message: | + AES algorithms requires an initialization vector (IV). Providing no or null IV in some implementation results to a 0 IV. Use of a deterministic IV makes dictionary attacks easier. + languages: + - "javascript" + severity: "WARNING" + metadata: + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + cwe: "CWE-327" + shortDescription: "Use of a broken or risky cryptographic algorithm" + security-severity: "MEDIUM" + category: "security" +- id: rules_lgpl_javascript_crypto_rule-node-insecure-random-generator + pattern-either: + - patterns: + - pattern-inside: | + require('crypto') + ... + - pattern: | + $X.pseudoRandomBytes(...) + - pattern: | + Math.random(...) + message: | + This rule identifies use of cryptographically weak random number generators. + Using cryptographically weak random number generators like `crypto.pseudoRandomBytes()` + and `Math.random()` for security-critical tasks can expose systems to significant + vulnerabilities. Attackers might predict the generated random numbers, compromising + the integrity and confidentiality of cryptographic operations. This could lead to + breaches where sensitive data is accessed or manipulated, authentication mechanisms + are bypassed, or secure communications are intercepted, ultimately undermining the + security of the entire system or application. + + Mitigation strategy: + Replace the use of these cryptographically weak random number generators with + `crypto.randomBytes()`, a method provided by Node.js's `crypto` module that + generates cryptographically secure random numbers. This method should be used + for all operations requiring secure randomness, such as generating keys, tokens, + or any cryptographic material. + + Secure Code Example: + ``` + const crypto = require('crypto'); + const secureBytes = crypto.randomBytes(256); + console.log(`Secure random bytes: ${secureBytes.toString('hex')}`); + ``` + languages: + - "javascript" + severity: "WARNING" + metadata: + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + cwe: "CWE-338" + shortDescription: "Use of cryptographically weak pseudo-random number generator (PRNG)" + security-severity: "MEDIUM" + category: "security" + +- id: rules_lgpl_javascript_crypto_rule-node-md5 + pattern-either: + - patterns: + - pattern-either: + - patterns: + - pattern-inside: | + $Y = $X.createHash('md5') + ... + - pattern: | + $Y.update("...") + - pattern: | + $X.createHash('md5').update("...") + - patterns: + - pattern-inside: | + require('crypto-js') + ... + - pattern: | + $X.MD5("...") + - patterns: + - pattern-either: + - pattern-inside: | + $M = require('md5') + ... + - pattern-inside: | + $M = require('blueimp-md5') + ... + - pattern-inside: | + $M = require('js-md5') + ... + - pattern: | + $M("...") + - patterns: + - pattern-inside: | + require('node-forge') + ... + - pattern-either: + - patterns: + - pattern-inside: | + $Y = $X.md.md5.create() + ... + - pattern: | + $Y.update("...") + - pattern: | + $X.md.md5.create().update("...") + - patterns: + - pattern-inside: | + $X = require('jshashes') + ... + $Y = new $X.MD5() + ... + - pattern: | + $Y.$METHOD("...") + - patterns: + - pattern-either: + - patterns: + - pattern-inside: | + $X = require('create-hash') + ... + $Y = $X('md5') + ... + - pattern: | + $Y.update("...") + - patterns: + - pattern-inside: | + $X = require('create-hash') + ... + - pattern: | + $X('md5').update("...") + message: | + The MD5 hashing algorithm is considered cryptographically weak and + vulnerable to collision attacks, where two different inputs generate + the same output hash. When used for hashing sensitive data, attackers + can exploit this weakness to generate collisions, allowing them to bypass + security checks or masquerade malicious data as legitimate. This + vulnerability is particularly critical in authentication mechanisms, + digital signatures, SSL/TLS certificates, and data integrity checks. + + Remediation: + To mitigate this vulnerability, replace the MD5 hashing algorithm with + stronger cryptographic hash functions, such as SHA-256 or SHA-3. These + algorithms offer significantly improved security and are resistant to + collision attacks, making them suitable for cryptographic purposes in + modern applications. + + Secure Code example : + ``` + const crypto = require('crypto'); + const hash = crypto.createHash('sha256').update('sensitive data').digest('hex'); + console.log(hash); + ``` + languages: + - "javascript" + severity: "WARNING" + metadata: + shortDescription: "Use of weak hash" + category: "security" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + cwe: "CWE-328" + security-severity: "MEDIUM" + +- id: rules_lgpl_javascript_crypto_rule-node-sha1 + pattern-either: + - patterns: + - pattern-either: + - patterns: + - pattern-inside: | + $Y = $X.createHash('sha1') + ... + - pattern: | + $Y.update("...") + - pattern: | + $X.createHash('sha1').update("...") + - patterns: + - pattern-inside: | + require('crypto-js') + ... + - pattern: | + $X.SHA1("...") + - patterns: + - pattern-either: + - pattern-inside: | + $M = require('sha1') + ... + - pattern-inside: | + $M = require('js-sha1') + ... + - pattern: | + $M("...") + - patterns: + - pattern-inside: | + require('node-forge') + ... + - pattern-either: + - patterns: + - pattern-inside: | + $Y = $X.md.sha1.create() + ... + - pattern: | + $Y.update("...") + - pattern: | + $X.md.sha1.create().update("...") + - patterns: + - pattern-inside: | + $X = require('jshashes') + ... + $Y = new $X.SHA1() + ... + - pattern: | + $Y.$METHOD("...") + - patterns: + - pattern-inside: | + require('hash.js') + ... + - pattern-either: + - patterns: + - pattern-inside: | + $Y = $X.sha1() + ... + - pattern: | + $Y.update("...") + - pattern: | + $X.sha1().update("...") + - patterns: + - pattern-inside: | + $X = require('jssha') + ... + - pattern-either: + - pattern: | + new $X('SHA-1', ...).update("...") + - patterns: + - pattern-inside: | + $Y = new $X('SHA-1', ...) + ... + - pattern: | + $Y.update("...") + - patterns: + - pattern-either: + - pattern: | + $X('sha1').update("...") + - patterns: + - pattern-inside: | + $Y = $X('sha1') + ... + - pattern: | + $Y.update("...") + - pattern: | + $X.subtle.digest('SHA-1', ...) + - patterns: + - pattern-either: + - pattern: | + $X.SHA1.digest(...) + - patterns: + - pattern-inside: | + $Y = $X.SHA1 + ... + - pattern: | + $Y.digest(...) + - patterns: + - pattern-either: + - pattern: | + $X.codec.hex.fromBits($SJCL) + - patterns: + - pattern-inside: | + $Y = $SJCL + ... + - pattern: | + $X.codec.hex.fromBits($Y) + - metavariable-pattern: + metavariable: $SJCL + pattern: | + $K.hash.sha1.hash("...") + message: | + The SHA-1 hashing algorithm is no longer considered secure for + cryptographic applications due to its vulnerability to collision attacks, + where two different inputs produce the same output hash. SHA-1's + susceptibility to collision attacks undermines the security of + cryptographic operations, allowing attackers to forge signatures or + manipulate data without detection. This poses significant risks in + authentication systems, data integrity validations, and secure + communications. + + Remediation: To mitigate this vulnerability, replace the SHA1 hashing + algorithm with stronger cryptographic hash functions, such as SHA-256 + or SHA-3. These algorithms offer significantly improved security and + are resistant to collision attacks, making them suitable for cryptographic + purposes in modern applications. + + Secure Code example: + ``` + const crypto = require('crypto'); + const hash = crypto.createHash('sha256').update('sensitive data').digest('hex'); + console.log(hash); + ``` + languages: + - "javascript" + severity: "WARNING" + metadata: + shortDescription: "Use of weak hash" + category: "security" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + cwe: "CWE-328" + security-severity: "MEDIUM" +- id: rules_lgpl_javascript_crypto_rule-node-timing-attack + patterns: + - pattern-not: "if ($Z == null) { ... };" + - pattern-not: "if ($Z === null) { ... };" + - pattern-not: "if ($Z != null) { ... };" + - pattern-not: "if ($Z !== null) { ... };" + - pattern-not: "if ($Q != undefined) { ... };" + - pattern-not: "if ($Q !== undefined) { ... };" + - pattern-not: "if ($Q == undefined) { ... };" + - pattern-not: "if ($Q === undefined) { ... };" + - pattern-not: "return $Y == null;" + - pattern-not: "return $Y === null;" + - pattern-not: "return $Y != null;" + - pattern-not: "return $Y !== null;" + - pattern-not: "return $Y == undefined;" + - pattern-not: "return $Y === undefined;" + - pattern-not: "return $Y != undefined;" + - pattern-not: "return $Y !== undefined;" + - pattern-either: + - pattern: | + if (password == $X) { + ... + } + - pattern: | + if ($X == password) { + ... + } + - pattern: | + if (password === $X) { + ... + } + - pattern: | + if ($X === password) { + ... + } + - pattern: | + if (pass == $X) { + ... + } + - pattern: | + if ($X == pass) { + ... + } + - pattern: | + if (pass === $X) { + ... + } + - pattern: | + if ($X === pass) { + ... + } + - pattern: | + if (secret == $X) { + ... + } + - pattern: | + if ($X == secret) { + ... + } + - pattern: | + if (secret === $X) { + ... + } + - pattern: | + if ($X === secret) { + ... + } + - pattern: | + if (api == $X) { + ... + } + - pattern: | + if ($X == api) { + ... + } + - pattern: | + if (api === $X) { + ... + } + - pattern: | + if ($X === api) { + ... + } + - pattern: | + if (apiKey == $X) { + ... + } + - pattern: | + if ($X == apiKey) { + ... + } + - pattern: | + if (apiKey === $X) { + ... + } + - pattern: | + if ($X === apiKey) { + ... + } + - pattern: | + if (apiSecret == $X) { + ... + } + - pattern: | + if ($X == apiSecret) { + ... + } + - pattern: | + if (apiSecret === $X) { + ... + } + - pattern: | + if ($X === apiSecret) { + ... + } + - pattern: | + if (token == $X) { + ... + } + - pattern: | + if ($X == token) { + ... + } + - pattern: | + if (token === $X) { + ... + } + - pattern: | + if ($X === token) { + ... + } + - pattern: | + if (hash == $X) { + ... + } + - pattern: | + if ($X == hash) { + ... + } + - pattern: | + if (hash === $X) { + ... + } + - pattern: | + if ($X === hash) { + ... + } + - pattern: | + if (auth_token == $X) { + ... + } + - pattern: | + if ($X == auth_token) { + ... + } + - pattern: | + if (auth_token === $X) { + ... + } + - pattern: | + if ($X === auth_token) { + ... + } + - pattern: | + if (password != $X) { + ... + } + - pattern: | + if ($X != password) { + ... + } + - pattern: | + if (password !== $X) { + ... + } + - pattern: | + if ($X !== password) { + ... + } + - pattern: | + if (pass != $X) { + ... + } + - pattern: | + if ($X != pass) { + ... + } + - pattern: | + if (pass !== $X) { + ... + } + - pattern: | + if ($X !== pass) { + ... + } + - pattern: | + if (secret != $X) { + ... + } + - pattern: | + if ($X != secret) { + ... + } + - pattern: | + if (secret !== $X) { + ... + } + - pattern: | + if ($X !== secret) { + ... + } + - pattern: | + if (api != $X) { + ... + } + - pattern: | + if ($X != api) { + ... + } + - pattern: | + if (api !== $X) { + ... + } + - pattern: | + if ($X !== api) { + ... + } + - pattern: | + if (apiKey != $X) { + ... + } + - pattern: | + if ($X != apiKey) { + ... + } + - pattern: | + if (apiKey !== $X) { + ... + } + - pattern: | + if ($X !== apiKey) { + ... + } + - pattern: | + if (apiSecret != $X) { + ... + } + - pattern: | + if ($X != apiSecret) { + ... + } + - pattern: | + if (apiSecret !== $X) { + ... + } + - pattern: | + if ($X !== apiSecret) { + ... + } + - pattern: | + if (token != $X) { + ... + } + - pattern: | + if ($X != token) { + ... + } + - pattern: | + if (token !== $X) { + ... + } + - pattern: | + if ($X !== token) { + ... + } + - pattern: | + if (hash != $X) { + ... + } + - pattern: | + if ($X != hash) { + ... + } + - pattern: | + if (hash !== $X) { + ... + } + - pattern: | + if ($X !== hash) { + ... + } + - pattern: | + if (auth_token != $X) { + ... + } + - pattern: | + if ($X != auth_token) { + ... + } + - pattern: | + if (auth_token !== $X) { + ... + } + - pattern: | + if ($X !== auth_token) { + ... + } + - pattern: | + return $X === auth_token; + - pattern: | + return auth_token === $X; + - pattern: | + return $X === token; + - pattern: | + return token === $X; + - pattern: | + return $X === hash; + - pattern: | + return hash === $X; + - pattern: | + return $X === password; + - pattern: | + return password === $X; + - pattern: | + return $X === pass; + - pattern: | + return pass === $X; + - pattern: | + return $X === apiKey; + - pattern: | + return apiKey === $X; + - pattern: | + return $X === apiSecret; + - pattern: | + return apiSecret === $X; + - pattern: | + return $X === api_key; + - pattern: | + return api_key === $X; + - pattern: | + return $X === api_secret; + - pattern: | + return api_secret === $X; + - pattern: | + return $X === secret; + - pattern: | + return secret === $X; + - pattern: | + return $X === api; + - pattern: | + return api === $X; + - pattern: | + return $X == auth_token; + - pattern: | + return auth_token == $X; + - pattern: | + return $X == token; + - pattern: | + return token == $X; + - pattern: | + return $X == hash; + - pattern: | + return hash == $X; + - pattern: | + return $X == password; + - pattern: | + return password == $X; + - pattern: | + return $X == pass; + - pattern: | + return pass == $X; + - pattern: | + return $X == apiKey; + - pattern: | + return apiKey == $X; + - pattern: | + return $X == apiSecret; + - pattern: | + return apiSecret == $X; + - pattern: | + return $X == api_key; + - pattern: | + return api_key == $X; + - pattern: | + return $X == api_secret; + - pattern: | + return api_secret == $X; + - pattern: | + return $X == secret; + - pattern: | + return secret == $X; + - pattern: | + return $X == api; + - pattern: | + return api == $X; + - pattern: | + return $X !== auth_token; + - pattern: | + return auth_token !== $X; + - pattern: | + return $X !== token; + - pattern: | + return token !== $X; + - pattern: | + return $X !== hash; + - pattern: | + return hash !== $X; + - pattern: | + return $X !== password; + - pattern: | + return password !== $X; + - pattern: | + return $X !== pass; + - pattern: | + return pass !== $X; + - pattern: | + return $X !== apiKey; + - pattern: | + return apiKey !== $X; + - pattern: | + return $X !== apiSecret; + - pattern: | + return apiSecret !== $X; + - pattern: | + return $X !== api_key; + - pattern: | + return api_key !== $X; + - pattern: | + return $X !== api_secret; + - pattern: | + return api_secret !== $X; + - pattern: | + return $X !== secret; + - pattern: | + return secret !== $X; + - pattern: | + return $X !== api; + - pattern: | + return api !== $X; + - pattern: | + return $X != auth_token; + - pattern: | + return auth_token != $X; + - pattern: | + return $X != token; + - pattern: | + return token != $X; + - pattern: | + return $X != hash; + - pattern: | + return hash != $X; + - pattern: | + return $X != password; + - pattern: | + return password != $X; + - pattern: | + return $X != pass; + - pattern: | + return pass != $X; + - pattern: | + return $X != apiKey; + - pattern: | + return apiKey != $X; + - pattern: | + return $X != apiSecret; + - pattern: | + return apiSecret != $X; + - pattern: | + return $X != api_key; + - pattern: | + return api_key != $X; + - pattern: | + return $X != api_secret; + - pattern: | + return api_secret != $X; + - pattern: | + return $X != secret; + - pattern: | + return secret != $X; + - pattern: | + return $X != api; + - pattern: | + return api != $X; + message: | + 'String comparisons using ''==='', ''!=='', ''!='' and ''=='' is vulnerable to timing attacks. More info: https://snyk.io/blog/node-js-timing-attack-ccc-ctf/' + languages: + - "javascript" + severity: "WARNING" + metadata: + cwe: "CWE-208" + shortDescription: "Observable timing discrepancy" + category: "security" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + security-severity: "MEDIUM" +- id: rules_lgpl_javascript_crypto_rule-node-tls-reject + patterns: + - pattern-either: + - pattern: | + $X.env.NODE_TLS_REJECT_UNAUTHORIZED = $VAL + - pattern: | + $X.env['NODE_TLS_REJECT_UNAUTHORIZED']= $VAL + - metavariable-pattern: + metavariable: $VAL + pattern-either: + - pattern: | + '0' + - pattern: | + 0 + message: | + The application sets NODE_TLS_REJECT_UNAUTHORIZED to '0', which instructs Node.js to disable TLS/SSL certificate validation. + This configuration allows the application to accept self-signed certificates or certificates from untrusted authorities, + undermining the TLS security model. Disabling TLS/SSL certificate validation compromises the integrity and confidentiality + of data in transit between the client and server. It makes the application vulnerable to man-in-the-middle (MITM) attacks, + where an attacker could intercept or alter the data being exchanged. + + Mitigation Strategy: + Do not disable TLS/SSL certificate validation in production environments. Ensure that NODE_TLS_REJECT_UNAUTHORIZED is + set to '1' or is removed entirely from the production configuration (as the default configuration of validating SSL + certificate is safe). + + Secure Code Example: + ``` + const https = require('https') + process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '1' + const req = https.request(options, res => { + let data = '' + res.on('data', chunk => { + data += chunk + }) + res.on('end', () => { + console.log('Response Body:', data) + }) + }) + req.end() + ``` + languages: + - "javascript" + severity: "WARNING" + metadata: + owasp: + - "A6:2017-Security Misconfiguration" + - "A05:2021-Security Misconfiguration" + cwe: "CWE-295" + shortDescription: "Improper Certificate Validation" + security-severity: "MEDIUM" + category: "security" +- id: rules_lgpl_javascript_crypto_rule-node-weak-crypto + patterns: + - pattern-either: + - pattern: | + $X.createCipher('des', ...) + message: | + A weak or broken cryptographic algorithm was identified. Using these functions will introduce vulnerabilities or downgrade the security of your application. + languages: + - "javascript" + severity: "WARNING" + metadata: + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + cwe: "CWE-327" + shortDescription: "Use of a broken or risky cryptographic algorithm" + security-severity: "MEDIUM" + category: "security" +- id: rules_lgpl_javascript_database_rule-node-knex-sqli-injection + patterns: + - pattern-either: + - pattern-inside: | + $KNEX = require('knex') + ... + - pattern-inside: | + $KNEX = require('knex')(...) + ... + - pattern-either: + - pattern: | + $K.raw(<... $REQ.$QUERY.$VAR ...>, ...) + - pattern: | + $K.raw(<... $REQ.$QUERY ...>, ...) + - pattern: | + $SQL = <... $REQ.$QUERY.$VAR ...>; + ... + $K.raw(<... $SQL ...>, ...) + - pattern: | + $SQL = <... $REQ.$QUERY ...>; + ... + $K.raw(<... $SQL ...>, ...) + - pattern: | + $INP = <... $REQ.$QUERY.$VAR ...>; + ... + $SQL = <... $INP ...>; + ... + $K.raw(<... $SQL ...>, ...) + - pattern: | + $INP = <... $REQ.$QUERY ...>; + ... + $SQL = <... $INP ...>; + ... + $K.raw(<... $SQL ...>, ...) + - pattern: | + $K.whereRaw(<... $REQ.$QUERY.$VAR ...>, ...) + - pattern: | + $K.whereRaw(<... $REQ.$QUERY ...>, ...) + - pattern: | + $SQL = <... $REQ.$QUERY.$VAR ...>; + ... + $K.whereRaw(<... $SQL ...>, ...) + - pattern: | + $SQL = <... $REQ.$QUERY ...>; + ... + $K.whereRaw(<... $SQL ...>, ...) + - pattern: | + $INP = <... $REQ.$QUERY.$VAR ...>; + ... + $SQL = <... $INP ...>; + ... + $K.whereRaw(<... $SQL ...>, ...) + - pattern: | + $INP = <... $REQ.$QUERY ...>; + ... + $SQL = <... $INP ...>; + ... + $K.whereRaw(<... $SQL ...>, ...) + message: | + Untrusted input concatinated with raw SQL query using knex raw() or whereRaw() functions can result in SQL Injection. + languages: + - "javascript" + severity: "ERROR" + metadata: + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + cwe: "CWE-89" + shortDescription: "Improper neutralization of special elements used in an SQL command + (SQL Injection)" + security-severity: "CRITICAL" + category: "security" +- id: rules_lgpl_javascript_database_rule-node-nosqli-injection + patterns: + - pattern-not-inside: | + $SANITIZE = require('mongo-sanitize') + ... + $SANITIZE(...) + ... + - pattern-not-inside: | + import $SANITIZE from 'mongo-sanitize' + ... + $SANITIZE(...) + ... + - pattern-not: | + $OBJ.findOne({$KEY : String(...).$FUNC()}, ...) + - pattern-not: | + $OBJ.findOne({$KEY : String(...).$FUNC}, ...) + - pattern-not: | + $OBJ.findOne({$KEY : String(...)}, ...) + - pattern-either: + - pattern: | + $OBJ.findOne({$KEY : <... $REQ.$FOO.$BAR ...> }, ...) + - pattern: | + $OBJ.findOne({$KEY: <... $REQ.$FOO ...> }, ...) + - pattern: | + $INP = <... $REQ.$FOO.$BAR ...>; + ... + $OBJ.findOne({$KEY : <... $INP ...> }, ...) + - pattern: | + $INP = <... $REQ.$FOO ...>; + ... + $OBJ.findOne({$KEY: <... $INP ...> }, ...) + - pattern: | + $QUERY = {$KEY: <... $REQ.$FOO.$BAR ...>}; + ... + $OBJ.findOne($QUERY, ...) + - pattern: | + $QUERY = {$KEY: <... $REQ.$FOO ...>}; + ... + $OBJ.findOne($QUERY, ...) + - pattern: | + $INP = <... $REQ.$FOO.$BAR ...>; + ... + $QUERY = {$KEY : <... $INP ...> }; + ... + $OBJ.findOne(<... $QUERY ...>, ...) + - pattern: | + $INP = <... $REQ.$FOO ...>; + ... + $QUERY = {$KEY : <... $INP ...> }; + ... + $OBJ.findOne(<... $QUERY ...>, ...) + - pattern: | + $QUERY[$KEY] = <... $REQ.$FOO.$BAR ...>; + ... + $OBJ.findOne($QUERY, ...) + - pattern: | + $QUERY[$KEY] = <... $REQ.$FOO ...>; + ... + $OBJ.findOne($QUERY, ...) + - pattern: | + $INP = <... $REQ.$FOO.$BAR ...>; + ... + $QUERY[$KEY] = <... $INP ...>; + ... + $OBJ.findOne(<... $QUERY ...>, ...) + - pattern: | + $INP = <... $REQ.$FOO ...>; + ... + $QUERY[$KEY] = <... $INP ...>; + ... + $OBJ.findOne(<... $QUERY ...>, ...) + message: | + Untrusted user input in findOne() function can result in NoSQL Injection. + languages: + - "javascript" + severity: "ERROR" + metadata: + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + cwe: "CWE-943" + shortDescription: "Improper neutralization of special elements in data query logic" + security-severity: "CRITICAL" + category: "security" +- id: rules_lgpl_javascript_database_rule-node-nosqli-js-injection + patterns: + - pattern-either: + - pattern: | + $OBJ.$FUNC({$where: <... $REQ.$FOO.$BAR ...>}, ...) + - pattern: | + $OBJ.$FUNC({$where: <... $REQ.$QUERY ...>}, ...) + - pattern: | + $NSQL = <... $REQ.$QUERY.$...>; + ... + $OBJ.$FUNC({$where: <... $NSQL ...>}, ...) + - pattern: | + $NSQL = <... $REQ.$QUERY ...>; + ... + $OBJ.$FUNC({$where: <... $NSQL ...>}, ...) + - pattern: | + $INP = $REQ.$FOO.$BAR; + ... + $QRY = {$where: <... $INP ...>}; + ... + $OBJ.$FUNC(<... $QRY ...>, ...) + - pattern: | + $INP = $REQ.$FOO; + ... + $QRY = {$where: <... $INP ...>}; + ... + $OBJ.$FUNC(<... $QRY ...>, ...) + - pattern: | + $QRY["$where"] = <... $REQ.$FOO ...>; + ... + $OBJ.$FUNC(<... $QRY ...>, ...) + - pattern: | + $QRY["$where"] = <... $REQ.$FOO.$BAR ...>; + ... + $OBJ.$FUNC(<... $QRY ...>, ...) + - pattern: | + $INP = $REQ.$FOO; + ... + $QRY["$where"] = <... $INP ...>; + ... + $OBJ.$FUNC(<... $QRY ...>, ...) + - pattern: | + $INP = $REQ.$FOO.$BAR; + ... + $QRY["$where"] = <... $INP ...>; + ... + $OBJ.$FUNC(<... $QRY ...>, ...) + message: | + Untrusted user input in MongoDB $where operator can result in NoSQL JavaScript Injection. + languages: + - "javascript" + severity: "ERROR" + metadata: + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + cwe: "CWE-943" + shortDescription: "Improper neutralization of special elements in data query logic" + security-severity: "CRITICAL" + category: "security" +- id: rules_lgpl_javascript_database_rule-node-sqli-injection + patterns: + - pattern-inside: | + require('$LIB') + ... + - metavariable-regex: + metavariable: "$LIB" + regex: "\\b(sql-client|mysql|pg|mssql|oracledb|sequelize)\\b" + - pattern-not: | + $CON.query("..." + "...", ...) + - pattern-not: | + $SQL = "..."; + ... + $CON.query(<... $SQL ...>, ...) + - pattern-either: + - pattern: | + $CON.query(<... $REQ.$QUERY ...>, ...) + - pattern: | + $SQL = <... $REQ.$QUERY ...>; + ... + $CON.query(<... $SQL ...>, ...) + - pattern: | + $INP = <... $REQ.$QUERY ...>; + ... + $SQL = <... $INP ...>; + ... + $CON.query(<... $SQL ...>, ...) + - pattern: | + $CON.query(`...${...}...`, ...) + - pattern: | + $CON.query("..."+...+"...", ...) + - pattern: | + $SQL = <... $INP ...>; + ... + $CON.query(<... $SQL ...>, ...) + message: | + Untrusted input concatinated with raw SQL query can result in SQL Injection. + languages: + - "javascript" + severity: "ERROR" + metadata: + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + cwe: "CWE-89" + shortDescription: "Improper neutralization of special elements used in an SQL command + (SQL Injection)" + security-severity: "CRITICAL" + category: "security" +- id: rules_lgpl_javascript_database_rule-sequelize-tls + message: | + 'The Sequelize connection string indicates that database server does not use TLS. Non TLS connections are susceptible to man in the middle (MITM) attacks.' + languages: + - "javascript" + severity: "WARNING" + metadata: + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + cwe: "CWE-319" + shortDescription: "Cleartext transmission of sensitive information" + security-severity: "MEDIUM" + category: "security" + patterns: + - pattern: | + { + host: $HOST, + database: $DATABASE, + dialect: $DIALECT + } + - pattern-not: | + { + host: $HOST, + database: $DATABASE, + dialect: "postgres", + dialectOptions: { + ssl: true + } + } + - pattern-not: | + { + host: $HOST, + database: $DATABASE, + dialect: $DIALECT, + dialectOptions: { + ssl: { ... } + } + } + - metavariable-regex: + metavariable: "$DIALECT" + regex: "['\"](mariadb|mysql|postgres|oracle)['\"]" +- id: rules_lgpl_javascript_database_rule-sequelize-tls-cert-validation + message: | + The Sequelize connection string indicates that TLS certificate validation + of database server is disabled. This is equivalent to not having TLS. An + attacker can present any invalid certificate and Sequelize will make database + connection ignoring certificate errors. This setting make the connection + susceptible to man in the middle (MITM) attacks. Not applicable to SQLite database. + severity: "ERROR" + languages: + - "javascript" + metadata: + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + cwe: "CWE-295" + shortDescription: "Improper certificate validation" + security-severity: "HIGH" + category: "security" + patterns: + - pattern: | + { + host: $HOST, + database: $DATABASE, + dialect: $DIALECT, + dialectOptions: { + ssl: { + rejectUnauthorized: false + } + } + } + - metavariable-regex: + metavariable: "$DIALECT" + regex: "['\"](mariadb|mysql|postgres)['\"]" +- id: rules_lgpl_javascript_database_rule-sequelize-weak-tls + message: | + 'The Sequelize connection string indicates that an older version of TLS is in use. TLS1.0 and TLS1.1 are deprecated and should be used. By default, Sequelize use TLSv1.2 but it''s recommended to use TLS1.3. Not applicable to SQLite database.' + metadata: + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + cwe: "CWE-757" + shortDescription: "Selection of Less-Secure Algorithm During Negotiation (Algorithm + Downgrade)" + security-severity: "CRITICAL" + category: "security" + severity: "ERROR" + languages: + - "javascript" + patterns: + - pattern-inside: | + { + host: $HOST, + database: $DATABASE, + dialect: $DIALECT, + dialectOptions: + { ssl: ... } + } + - pattern-either: + - pattern: | + { + minVersion: 'TLSv1' + } + - pattern: | + { + minVersion: 'TLSv1.1' + } + - metavariable-regex: + metavariable: "$DIALECT" + regex: "['\"](mariadb|mysql|postgres)['\"]" +- id: rules_lgpl_javascript_dos_rule-layer7-object-dos + mode: taint + pattern-sources: + - patterns: + - pattern-inside: function ($REQ, $RES, ...) {...} + - pattern: $REQ.$FUNC. ... + - metavariable-regex: + metavariable: "$FUNC" + regex: "^(body|params|query|baseUrl|cookies|hostname|subdomains|ip|ips|originalUrl|path)$" + pattern-sinks: + - patterns: + - pattern: | + for(...; $COND; ...){...} + - focus-metavariable: $COND + - metavariable-pattern: + metavariable: $COND + pattern-either: + - pattern: | + Object.Keys($VAR).length + - pattern: $VAR.length + - patterns: + - pattern-either: + - pattern: $OBJ.forEach + - pattern: $OBJ.map + - pattern: Object.keys($OBJ).map + - pattern: $OBJ.filter + - pattern: $OBJ.reduce + - pattern: $OBJ.reduceRight + - focus-metavariable: $OBJ + message: | + This application is looping over user controlled objects, which can lead to a layer 7 denial of service vulnerability. + + A layer 7 denial of service attack refers to overloading the application layer of the OSI model, typically layer 7. + This can happen when user-controlled input such as objects, arrays, strings, etc. are iterated or looped over without proper validation or limits in place. + + For example, if a user can control the size of an array or object passed into the application, + they could create an extremely large input that gets looped over. This would consume excessive CPU cycles or memory, + potentially crashing or slowing down the application. + + To prevent this, limits should be set on the number of iterations, input sizes, recursion depth, etc. + + Sample case of secure array looped over with user-controlled input + ``` + // Potential DoS if req.body.list.length is large. + app.post('/dos/layer7-object-dos/for-loop/1', function (req, res) { + var list = req.body.list; + for (let i = 0; i <= 10; i++) { + if(!list[i]){ + // return; + } + } + res.send("res") + }); + ``` + + Implementing protections against layer 7 denial of service attacks is important for securing modern web applications and APIs. + languages: + - "javascript" + severity: "WARNING" + metadata: + owasp: + - "A6:2017-Security Misconfiguration" + - "A05:2021-Security Misconfiguration" + cwe: "CWE-606" + shortDescription: "Unchecked input for loop condition" + security-severity: "MEDIUM" + category: "security" +- id: rules_lgpl_javascript_dos_rule-regex-dos + patterns: + - pattern-either: + - pattern-inside: |- + function ($REQ, $RES, ...) {...} + - pattern-inside: |- + function $FUNC($REQ, $RES, ...) {...} + - pattern-inside: |- + $X = function $FUNC($REQ, $RES, ...) {...} + - pattern-inside: |- + var $X = function $FUNC($REQ, $RES, ...) {...}; + - pattern-inside: |- + $APP.$METHOD(..., function $FUNC($REQ, $RES, ...) {...}) + - pattern-either: + - pattern: | + $REGEX.test(<... $REQ ...>) + - pattern: | + $REGEX.test(<... $REQ.$QUERY ...>) + - pattern: | + $REGEX.test(<... $REQ.$BODY.$PARAM ...>) + - pattern: | + $INP = <... $REQ ...>; + ... + $REGEX.test(<... $INP ...>) + - pattern: | + $INP = <... $REQ.$QUERY ...>; + ... + $REGEX.test(<... $INP ...>) + - pattern: | + $INP = <... $REQ.$BODY.$PARAM ...>; + ... + $REGEX.test(<... $INP ...>) + - pattern: | + /.../g.exec(<... $REQ ...>) + - pattern: | + /.../g.exec(<... $REQ.$QUERY ...>) + - pattern: | + /.../.exec(<... $REQ.$BODY.$PARAM ...>) + - pattern: | + $INP = <... $REQ ...>; + ... + /.../.exec(<... $INP ...>) + - pattern: | + $INP = <... $REQ.$QUERY ...>; + ... + /.../.exec(<... $INP ...>) + - pattern: | + $INP = <... $REQ.$BODY.$PARAM ...>; + ... + /.../.exec(<... $INP ...>) + - pattern: | + $RE = /.../; + ... + $RE.exec(<... $REQ ...>) + - pattern: | + $RE = /.../; + ... + $RE.exec(<... $REQ.$QUERY ...>) + - pattern: | + $RE = /.../; + ... + $RE.exec(<... $REQ.$BODY.$PARAM ...>) + message: | + Ensure that the regex used to compare with user supplied input is safe from regular expression denial of service. + languages: + - "javascript" + severity: "WARNING" + metadata: + owasp: + - "A6:2017-Security Misconfiguration" + - "A05:2021-Security Misconfiguration" + cwe: "CWE-185" + shortDescription: "Incorrect regular expression" + security-severity: "MEDIUM" + category: "security" +- id: rules_lgpl_javascript_electronjs_rule-electron-allow-http + patterns: + - pattern-either: + - pattern: | + new BrowserWindow({webPreferences: {allowRunningInsecureContent: true}}) + - pattern: | + var $X = {webPreferences: {allowRunningInsecureContent: true}}; + message: | + Application can load content over HTTP and that makes the app vulnerable to Man in the middle attacks. + languages: + - "javascript" + severity: "ERROR" + metadata: + owasp: + - "A6:2017-Security Misconfiguration" + - "A05:2021-Security Misconfiguration" + cwe: "CWE-319" + shortDescription: "Cleartext Transmission of Sensitive Information" + security-severity: "CRITICAL" + category: "security" +- id: rules_lgpl_javascript_electronjs_rule-electron-blink-integration + patterns: + - pattern-either: + - pattern: | + new BrowserWindow({webPreferences: {enableBlinkFeatures: '...'}}) + - pattern: | + var $X = {webPreferences: {enableBlinkFeatures: '...'}}; + message: | + Blink's expirimental features are enabled in this application. Some of the features may affect the security of the application. + languages: + - "javascript" + severity: "WARNING" + metadata: + owasp: + - "A6:2017-Security Misconfiguration" + - "A05:2021-Security Misconfiguration" + cwe: "CWE-272" + shortDescription: "Least privilege violation" + security-severity: "MEDIUM" + category: "security" +- id: rules_lgpl_javascript_electronjs_rule-electron-context-isolation + patterns: + - pattern-either: + - pattern: | + new BrowserWindow({webPreferences: {contextIsolation: false}}) + - pattern: | + var $X = {webPreferences: {contextIsolation: false}}; + message: | + Disabling context isolation can introduce Prototype Pollution vulnerabilities. + languages: + - "javascript" + severity: "WARNING" + metadata: + owasp: + - "A6:2017-Security Misconfiguration" + - "A05:2021-Security Misconfiguration" + cwe: "CWE-1321" + shortDescription: "Improperly controlled modification of object prototype attributes ('Prototype Pollution')" + security-severity: "MEDIUM" + category: "security" +- id: rules_lgpl_javascript_electronjs_rule-electron-disable-websecurity + patterns: + - pattern-either: + - pattern: | + new BrowserWindow({webPreferences: {webSecurity: false}}) + - pattern: | + var $X = {webPreferences: {webSecurity: false}}; + message: | + Disabling webSecurity will disable the same-origin policy and allows the execution of insecure code from any domain. + languages: + - "javascript" + severity: "ERROR" + metadata: + owasp: + - "A6:2017-Security Misconfiguration" + - "A05:2021-Security Misconfiguration" + cwe: "CWE-346" + shortDescription: "Origin validation error" + security-severity: "CRITICAL" + category: "security" +- id: rules_lgpl_javascript_electronjs_rule-electron-experimental-features + patterns: + - pattern-either: + - pattern: | + new BrowserWindow({webPreferences: {experimentalFeatures: true}}) + - pattern: | + var $X = {webPreferences: {experimentalFeatures: true}}; + message: | + Experimental features are not expected to be in production ready applications. + languages: + - "javascript" + severity: "WARNING" + metadata: + owasp: + - "A6:2017-Security Misconfiguration" + - "A05:2021-Security Misconfiguration" + cwe: "CWE-272" + shortDescription: "Least privilege violation" + security-severity: "CRITICAL" + category: "security" + +- id: rules_lgpl_javascript_electronjs_rule-electron-nodejs-integration + patterns: + - pattern-either: + - pattern: | + new BrowserWindow({webPreferences: {nodeIntegration: true}}) + - pattern: | + var $X = {webPreferences: {nodeIntegration: true}}; + message: | + Node integration exposes node.js APIs to the electron app and this can introduce remote code execution vulnerabilities to the application if the app is vulnerable to Cross Site Scripting (XSS). + languages: + - "javascript" + severity: "WARNING" + metadata: + owasp: + - "A6:2017-Security Misconfiguration" + - "A05:2021-Security Misconfiguration" + cwe: "CWE-272" + shortDescription: "Least privilege violation" + security-severity: "MEDIUM" + category: "security" +- id: rules_lgpl_javascript_eval_rule-eval-nodejs + patterns: + - pattern-either: + - pattern-inside: |- + function ($REQ, $RES, ...) {...} + - pattern-inside: |- + function $FUNC($REQ, $RES, ...) {...} + - pattern-inside: |- + $X = function $FUNC($REQ, $RES, ...) {...} + - pattern-inside: |- + var $X = function $FUNC($REQ, $RES, ...) {...}; + - pattern-inside: |- + $APP.$METHOD(..., function $FUNC($REQ, $RES, ...) {...}) + - pattern-either: + - pattern: | + new Function(..., <... $REQ.$QUERY.$VAR ...>, ...) + - pattern: | + new Function(..., <... $REQ.$QUERY ...>, ...) + - pattern: | + eval(..., <... $REQ.$QUERY.$VAR ...>, ...) + - pattern: | + eval(..., <... $REQ.$QUERY ...>, ...) + - pattern: | + setTimeout(..., <... $REQ.$QUERY.$VAR ...>, ...) + - pattern: | + setTimeout(..., <... $REQ.$QUERY ...>, ...) + - pattern: | + setInterval(..., <... $REQ.$QUERY.$VAR ...>, ...) + - pattern: | + setInterval(..., <... $REQ.$QUERY ...>, ...) + - pattern: | + $INP = <... $REQ.$QUERY.$VAR ...>; + ... + new Function(..., <... $INP ...>, ...) + - pattern: | + $INP = <... $REQ.$QUERY ...>; + ... + new Function(..., <... $INP ...>, ...) + - pattern: | + $INP = <... $REQ.$QUERY.$VAR ...>; + ... + eval(..., <... $INP ...>, ...) + - pattern: | + $INP = <... $REQ.$QUERY ...>; + ... + eval(..., <... $INP ...>, ...) + - pattern: | + $INP = <... $REQ.$QUERY.$VAR ...>; + ... + setTimeout(..., <... $INP ...>, ...) + - pattern: | + $INP = <... $REQ.$QUERY ...>; + ... + setTimeout(..., <... $INP ...>, ...) + - pattern: | + $INP = <... $REQ.$QUERY.$VAR ...>; + ... + setInterval(..., <... $INP ...>, ...) + - pattern: | + $INP = <... $REQ.$QUERY ...>; + ... + setInterval(..., <... $INP ...>, ...) + message: | + User controlled data in eval() or similar functions may result in Server Side Injection or Remote Code Injection + languages: + - "javascript" + severity: "ERROR" + metadata: + cwe: "CWE-95" + shortDescription: "Improper neutralization of directives in dynamically evaluated + code ('Eval Injection')" + category: "security" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "HIGH" +- id: rules_lgpl_javascript_eval_rule-eval-require + mode: taint + pattern-sources: + - patterns: + - pattern-inside: | + function ($REQ, $RES, ...) {...} + - focus-metavariable: $REQ + pattern-sinks: + - patterns: + - pattern: | + require($REQ, ...) + - focus-metavariable: $REQ + pattern-sanitizers: + - patterns: + - pattern-either: + - pattern: | + if($VALIDATION){ + ... + require($REQ, ...) + ... + } + - pattern: | + $A = $VALIDATION + ... + if($A){ + ... + require($REQ, ...) + ... + } + - metavariable-pattern: + metavariable: $VALIDATION + pattern-either: + - pattern: | + $AL.includes(...) + - pattern: | + $AL.indexOf(...) !== -1 + - pattern: | + $AL.find(...) !== undefined + - pattern: | + $ALS.has(...) + message: | + Passing untrusted user input directly into the require() function without proper + validation or sanitization can possibly cause a vulnerability known as remote code execution (RCE). + An attacker could manipulate the input to load and execute arbitrary code from external sources, + potentially leading to severe security breaches such as data theft, system compromise, + or unauthorized access. + To mitigate this risk, it's crucial to validate and sanitize user input + thoroughly before passing it to functions like require(), ensuring that only trusted and safe inputs are utilized. + + Following is an example of secure validation against allowlist to prevent the vulnerability: + ``` + // Define a list of explicitly allowed packages for require + const allowedPkgs = [ + 'package1', + 'package2', + 'package3' + ]; + + app.get("/eval/require/7", async (req, res) => { + var isAllowed = allowedPkgs.includes(req.query.name); + if (isAllowed) { + // ok: rules_lgpl_javascript_eval_rule-eval-require + var cp = require(req.query.name); + cp.exec('ls', (error, stdout, stderr) => { + console.log("exec output : \n", stdout) + }); + } + res.send("Please check console logs."); + }); + ``` + severity: "ERROR" + languages: + - "javascript" + metadata: + cwe: "CWE-706" + shortDescription: "Use of incorrectly-resolved name or reference" + category: "security" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "CRITICAL" +- id: rules_lgpl_javascript_eval_rule-grpc-insecure-connection + patterns: + - pattern-either: + - pattern-inside: | + require('grpc') + ... + - pattern-inside: | + import $MOD from 'grpc' + ... + - pattern: "$CREDENTIALS.createInsecure()" + message: | + Found an insecure gRPC connection. This creates a connection without encryption to a gRPC client/server. A malicious attacker could tamper with the gRPC message, which could compromise the machine. + metadata: + owasp: + - "A8:2017-Insecure Deserialization" + - "A08:2021-Software and Data Integrity Failures" + cwe: "CWE-502" + shortDescription: "Deserialization of Untrusted Data" + security-severity: "CRITICAL" + category: "security" + severity: "ERROR" + languages: + - "javascript" + - "typescript" +- id: rules_lgpl_javascript_eval_rule-node-deserialize + patterns: + - pattern-either: + - pattern: | + require('node-serialize').unserialize(...) + - pattern-inside: | + $MOD = require('node-serialize') + ... + - pattern-inside: | + import $MOD from 'node-serialize' + ... + - pattern: | + $MOD.unserialize(...) + message: | + User controlled data in 'unserialize()' or 'deserialize()' function can result in Object Injection or Remote Code Injection. + languages: + - "javascript" + - "typescript" + severity: "ERROR" + metadata: + owasp: + - "A8:2017-Insecure Deserialization" + - "A08:2021-Software and Data Integrity Failures" + cwe: "CWE-502" + shortDescription: "Deserialization of Untrusted Data" + security-severity: "CRITICAL" + category: "security" +- id: rules_lgpl_javascript_eval_rule-sandbox-code-injection + patterns: + - pattern-inside: | + require('sandbox') + ... + - pattern-either: + - pattern-inside: |- + function ($REQ, $RES, ...) {...} + - pattern-inside: |- + function $FUNC($REQ, $RES, ...) {...} + - pattern-inside: |- + $X = function $FUNC($REQ, $RES, ...) {...} + - pattern-inside: |- + var $X = function $FUNC($REQ, $RES, ...) {...}; + - pattern-inside: |- + $APP.$METHOD(..., function $FUNC($REQ, $RES, ...) {...}) + - pattern-either: + - pattern: | + $S.run(<... $REQ.$QUERY.$FOO ...>,...) + - pattern: | + $CODE = <... $REQ.$QUERY.$FOO ...>; + ... + $S.run(<... $CODE ...>,...) + - pattern: | + new $SANDBOX(...).run(<... $REQ.$QUERY.$FOO ...>,...) + - pattern: | + $CODE = <... $REQ.$QUERY.$FOO ...>; + ... + new $SANDBOX(...).run(<... $CODE ...>,...) + - pattern: | + $S.run(<... $REQ.$BODY ...>,...) + - pattern: | + $CODE = <... $REQ.$BODY ...>; + ... + $S.run(<... $CODE ...>,...) + - pattern: | + new $SANDBOX(...).run(<... $REQ.$BODY ...>,...) + - pattern: |- + $CODE = <... $REQ.$BODY ...>; + ... + new $SANDBOX(...).run(<... $CODE ...>,...) + message: | + Unrusted data in `sandbox` can result in code injection. + severity: "ERROR" + languages: + - "javascript" + metadata: + cwe: "CWE-94" + shortDescription: "Improper control of generation of code (Code Injection)" + category: "security" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "CRITICAL" +- id: rules_lgpl_javascript_eval_rule-serializetojs-deserialize + patterns: + - pattern-either: + - pattern: | + require('serialize-to-js').deserialize(...) + - pattern-inside: | + $MOD = require('serialize-to-js') + ... + - pattern-inside: | + import $MOD from 'serialize-to-js' + ... + - pattern: | + $MOD.deserialize(...) + message: | + User controlled data in 'unserialize()' or 'deserialize()' function can result in Object Injection or Remote Code Injection. + languages: + - "javascript" + - "typescript" + severity: "ERROR" + metadata: + owasp: + - "A8:2017-Insecure Deserialization" + - "A08:2021-Software and Data Integrity Failures" + cwe: "CWE-502" + shortDescription: "Deserialization of Untrusted Data" + security-severity: "CRITICAL" + category: "security" +- id: rules_lgpl_javascript_eval_rule-server-side-template-injection + patterns: + - pattern-either: + - pattern-inside: | + require('handlebars') + ... + - pattern-inside: | + require('pug') + ... + - pattern-inside: | + require('hamljs') + ... + - pattern-inside: | + require('ejs') + ... + - pattern-inside: | + require('squirrelly') + ... + - pattern-inside: | + require('eta') + ... + - pattern-either: + - pattern-inside: |- + function ($REQ, $RES, ...) {...} + - pattern-inside: |- + function $FUNC($REQ, $RES, ...) {...} + - pattern-inside: |- + $X = function $FUNC($REQ, $RES, ...) {...} + - pattern-inside: |- + var $X = function $FUNC($REQ, $RES, ...) {...}; + - pattern-inside: |- + $APP.$METHOD(..., function $FUNC($REQ, $RES, ...) {...}) + - pattern-either: + - pattern: | + $HB.compile(..., <... $REQ.$FOO ...>, ...) + - pattern: | + $HB.compile(..., <... $REQ.$FOO.$BAR ...>, ...) + - pattern: | + $X = <... $REQ.$FOO ...>; + ... + $HB.compile(..., <... $X ...>, ...) + - pattern: | + $X = <... $REQ.$FOO.$BAR ...>; + ... + $HB.compile(..., <... $X ...>, ...) + - pattern: | + $X = $SOURCE.replace('...', <... $REQ.$FOO ...>, ...) + ... + $HB.compile(..., <... $X ...>, ...) + - pattern: | + $X = $SOURCE.replace('...', <... $REQ.$FOO.$BAR ...>, ...) + ... + $HB.compile(..., <... $X ...>, ...) + - pattern: | + $HB.Compile(..., <... $REQ.$FOO ...>, ...) + - pattern: | + $HB.Compile(..., <... $REQ.$FOO.$BAR ...>, ...) + - pattern: | + $X = <... $REQ.$FOO ...>; + ... + $HB.Compile(..., <... $X ...>, ...) + - pattern: | + $X = <... $REQ.$FOO.$BAR ...>; + ... + $HB.Compile(..., <... $X ...>, ...) + - pattern: | + $X = $SOURCE.replace('...', <... $REQ.$FOO ...>, ...) + ... + $HB.Compile(..., <... $X ...>, ...) + - pattern: | + $X = $SOURCE.replace('...', <... $REQ.$FOO.$BAR ...>, ...) + ... + $HB.Compile(..., <... $X ...>, ...) + message: | + Untrusted user input in templating engine's compile() function can result in Remote Code Execution via server side template injection. + languages: + - "javascript" + severity: "ERROR" + metadata: + cwe: "CWE-94" + shortDescription: "Improper control of generation of code (Code Injection)" + category: "security" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "CRITICAL" +- id: rules_lgpl_javascript_eval_rule-vm2-code-injection + patterns: + - pattern-inside: | + require('vm2') + ... + - pattern-either: + - pattern-inside: |- + function ($REQ, $RES, ...) {...} + - pattern-inside: |- + function $FUNC($REQ, $RES, ...) {...} + - pattern-inside: |- + $X = function $FUNC($REQ, $RES, ...) {...} + - pattern-inside: |- + var $X = function $FUNC($REQ, $RES, ...) {...}; + - pattern-inside: |- + $APP.$METHOD(..., function $FUNC($REQ, $RES, ...) {...}) + - pattern-either: + - pattern: | + $VM.run(<... $REQ.$QUERY.$FOO ...>,...) + - pattern: | + $CODE = <... $REQ.$QUERY.$FOO ...>; + ... + $VM.run(<... $CODE ...>,...) + - pattern: | + new VM(...).run(<... $REQ.$QUERY.$FOO ...>,...) + - pattern: | + new NodeVM(...).run(<... $REQ.$QUERY.$FOO ...>,...) + - pattern: | + $CODE = <... $REQ.$QUERY.$FOO ...>; + ... + new NodeVM(...).run(<... $CODE ...>,...) + - pattern: | + $CODE = <... $REQ.$QUERY.$FOO ...>; + ... + new VMScript(<... $CODE ...>,...) + - pattern: | + $VM.run(<... $REQ.$BODY ...>,...) + - pattern: | + $CODE = <... $REQ.$BODY ...>; + ... + $VM.run(<... $CODE ...>,...) + - pattern: | + new VM(...).run(<... $REQ.$BODY ...>,...) + - pattern: | + $CODE = <... $REQ.$BODY ...>; + ... + new VM(...).run($CODE,...) + - pattern: | + new NodeVM(...).run(<... $REQ.$BODY ...>,...) + - pattern: | + $CODE = <... $REQ.$BODY ...>; + ... + new NodeVM(...).run(<... $CODE ...>,...) + - pattern: | + $CODE = <... $REQ.$BODY ...>; + ... + new VMScript(<... $CODE ...>,...) + message: | + Untrusted user input reaching `vm2` can result in code injection. + severity: "WARNING" + languages: + - "javascript" + metadata: + cwe: "CWE-94" + shortDescription: "Improper control of generation of code (Code Injection)" + category: "security" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "CRITICAL" +- id: rules_lgpl_javascript_eval_rule-vm2-context-injection + patterns: + - pattern-inside: | + require('vm2') + ... + - pattern-either: + - pattern-inside: |- + function ($REQ, $RES, ...) {...} + - pattern-inside: |- + function $FUNC($REQ, $RES, ...) {...} + - pattern-inside: |- + $X = function $FUNC($REQ, $RES, ...) {...} + - pattern-inside: |- + var $X = function $FUNC($REQ, $RES, ...) {...}; + - pattern-inside: |- + $APP.$METHOD(..., function $FUNC($REQ, $RES, ...) {...}) + - pattern-either: + - pattern: | + new VM({sandbox: <... $REQ.$QUERY.$FOO ...>},...) + - pattern: | + $CONTEXT = <... $REQ.$QUERY.$FOO ...>; + ... + new VM({sandbox: <... $CONTEXT ...>},...) + - pattern: | + $CONTEXT = <... {$NAME:$REQ.$QUERY.$FOO} ...>; + ... + new VM({sandbox: <... $CONTEXT ...>},...) + - pattern: | + $CONTEXT = {$NAME: <... $REQ.$QUERY.$FOO ...>}; + ... + new VM({sandbox: <... $CONTEXT ...>},...) + - pattern: | + $VAR = <... $REQ.$QUERY.$FOO ...>; + ... + $CONTEXT = {$NAME: <... $VAR ...>}; + ... + new VM({sandbox: <... $CONTEXT ...>},...) + - pattern: | + $OPTS = {sandbox: <... $REQ.$QUERY.$FOO ...>}; + ... + new VM($OPTS,...) + - pattern: | + $CONTEXT = <... $REQ.$QUERY.$FOO ...>; + ... + $OPTS = {sandbox: <... $CONTEXT ...>}; + ... + new VM($OPTS,...) + - pattern: | + $CONTEXT = {$NAME: <... $REQ.$QUERY.$FOO ...>}; + ... + $OPTS = {sandbox: <... $CONTEXT ...>}; + ... + new VM($OPTS,...) + - pattern: | + $VAR = <... $REQ.$QUERY.$FOO ...>; + ... + $CONTEXT = {$NAME: <... $VAR ...>}; + ... + $OPTS = {sandbox: <... $CONTEXT ...>}; + ... + new VM($OPTS,...) + - pattern: | + new NodeVM({sandbox: <... $REQ.$QUERY.$FOO ...>},...) + - pattern: | + $CONTEXT = <... $REQ.$QUERY.$FOO ...>; + ... + new NodeVM({sandbox: <... $CONTEXT ...>},...) + - pattern: | + $CONTEXT = <... {$NAME:$REQ.$QUERY.$FOO} ...>; + ... + new NodeVM({sandbox: <... $CONTEXT ...>},...) + - pattern: | + $CONTEXT = {$NAME: <... $REQ.$QUERY.$FOO ...>}; + ... + new NodeVM({sandbox: <... $CONTEXT ...>},...) + - pattern: | + $VAR = <... $REQ.$QUERY.$FOO ...>; + ... + $CONTEXT = {$NAME: <... $VAR ...>}; + ... + new NodeVM({sandbox: <... $CONTEXT ...>},...) + - pattern: | + $OPTS = {sandbox: <... $REQ.$QUERY.$FOO ...>}; + ... + new NodeVM($OPTS,...) + - pattern: | + $CONTEXT = <... $REQ.$QUERY.$FOO ...>; + ... + $OPTS = {sandbox: <... $CONTEXT ...>}; + ... + new NodeVM($OPTS,...) + - pattern: | + $CONTEXT = {$NAME: <... $REQ.$QUERY.$FOO ...>}; + ... + $OPTS = {sandbox: <... $CONTEXT ...>}; + ... + new NodeVM($OPTS,...) + - pattern: | + $VAR = <... $REQ.$QUERY.$FOO ...>; + ... + $CONTEXT = {$NAME: <... $VAR ...>}; + ... + $OPTS = {sandbox: <... $CONTEXT ...>}; + ... + new NodeVM($OPTS,...) + - pattern: | + new VM({sandbox: <... $REQ.$BODY ...>},...) + - pattern: | + $CONTEXT = <... $REQ.$BODY ...>; + ... + new VM({sandbox: <... $CONTEXT ...>},...) + - pattern: | + $CONTEXT = <... {$NAME:$REQ.$BODY} ...>; + ... + new VM({sandbox: <... $CONTEXT ...>},...) + - pattern: | + $CONTEXT = {$NAME: <... $REQ.$BODY ...>}; + ... + new VM({sandbox: <... $CONTEXT ...>},...) + - pattern: | + $VAR = <... $REQ.$BODY ...>; + ... + $CONTEXT = {$NAME: <... $VAR ...>}; + ... + new VM({sandbox: <... $CONTEXT ...>},...) + - pattern: | + $OPTS = {sandbox: <... $REQ.$BODY ...>}; + ... + new VM($OPTS,...) + - pattern: | + $CONTEXT = <... $REQ.$BODY ...>; + ... + $OPTS = {sandbox: <... $CONTEXT ...>}; + ... + new VM($OPTS,...) + - pattern: | + $CONTEXT = {$NAME: <... $REQ.$BODY ...>}; + ... + $OPTS = {sandbox: <... $CONTEXT ...>}; + ... + new VM($OPTS,...) + - pattern: | + $VAR = <... $REQ.$BODY ...>; + ... + $CONTEXT = {$NAME: <... $VAR ...>}; + ... + $OPTS = {sandbox: <... $CONTEXT ...>}; + ... + new VM($OPTS,...) + - pattern: | + new NodeVM({sandbox: <... $REQ.$BODY ...>},...) + - pattern: | + $CONTEXT = <... $REQ.$BODY ...>; + ... + new NodeVM({sandbox: <... $CONTEXT ...>},...) + - pattern: | + $CONTEXT = <... {$NAME:$REQ.$BODY} ...>; + ... + new NodeVM({sandbox: <... $CONTEXT ...>},...) + - pattern: | + $CONTEXT = {$NAME: <... $REQ.$BODY ...>}; + ... + new NodeVM({sandbox: <... $CONTEXT ...>},...) + - pattern: | + $VAR = <... $REQ.$BODY ...>; + ... + $CONTEXT = {$NAME: <... $VAR ...>}; + ... + new NodeVM({sandbox: <... $CONTEXT ...>},...) + - pattern: | + $OPTS = {sandbox: <... $REQ.$BODY ...>}; + ... + new NodeVM($OPTS,...) + - pattern: | + $CONTEXT = <... $REQ.$BODY ...>; + ... + $OPTS = {sandbox: <... $CONTEXT ...>}; + ... + new NodeVM($OPTS,...) + - pattern: | + $CONTEXT = {$NAME: <... $REQ.$BODY ...>}; + ... + $OPTS = {sandbox: <... $CONTEXT ...>}; + ... + new NodeVM($OPTS,...) + - pattern: |- + $VAR = <... $REQ.$BODY ...>; + ... + $CONTEXT = {$NAME: <... $VAR ...>}; + ... + $OPTS = {sandbox: <... $CONTEXT ...>}; + ... + new NodeVM($OPTS,...) + message: | + Untrusted user input reaching `vm2` sandbox can result in context injection. + severity: "ERROR" + languages: + - "javascript" + metadata: + cwe: "CWE-94" + shortDescription: "Improper control of generation of code (Code Injection)" + category: "security" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "CRITICAL" +- id: rules_lgpl_javascript_eval_rule-vm-code-injection + patterns: + - pattern-inside: | + $VM = require('vm') + ... + - pattern-either: + - pattern-inside: |- + function ($REQ, $RES, ...) {...} + - pattern-inside: |- + function $FUNC($REQ, $RES, ...) {...} + - pattern-inside: |- + $X = function $FUNC($REQ, $RES, ...) {...} + - pattern-inside: |- + var $X = function $FUNC($REQ, $RES, ...) {...}; + - pattern-inside: |- + $APP.$METHOD(..., function $FUNC($REQ, $RES, ...) {...}) + - pattern-either: + - pattern: "$VM.runInContext(<... $REQ.$QUERY.$FOO ...>,...)" + - pattern: "$VM.runInContext(<... $REQ.$BODY ...>,...)" + - pattern: | + $INPUT = <... $REQ.$QUERY.$FOO ...>; + ... + $VM.runInContext($INPUT,...) + - pattern: | + $INPUT = <... $REQ.$BODY ...>; + ... + $VM.runInContext($INPUT,...) + - pattern: "$VM.runInNewContext(<... $REQ.$QUERY.$FOO ...>,...)" + - pattern: "$VM.runInNewContext(<... $REQ.$BODY ...>,...)" + - pattern: | + $INPUT = <... $REQ.$QUERY.$FOO ...>; + ... + $VM.runInNewContext($INPUT,...) + - pattern: | + $INPUT = <... $REQ.$BODY ...>; + ... + $VM.runInNewContext($INPUT,...) + - pattern: "$VM.runInThisContext(<... $REQ.$QUERY.$FOO ...>,...)" + - pattern: "$VM.runInThisContext(<... $REQ.$BODY ...>,...)" + - pattern: | + $INPUT = <... $REQ.$QUERY.$FOO ...>; + ... + $VM.runInThisContext($INPUT,...) + - pattern: | + $INPUT = <... $REQ.$BODY ...>; + ... + $VM.runInThisContext($INPUT,...) + - pattern: "$VM.compileFunction(<... $REQ.$QUERY.$FOO ...>,...)" + - pattern: "$VM.compileFunction(<... $REQ.$BODY ...>,...)" + - pattern: | + $INPUT = <... $REQ.$QUERY.$FOO ...>; + ... + $VM.compileFunction($INPUT,...) + - pattern: | + $INPUT = <... $REQ.$BODY ...>; + ... + $VM.compileFunction($INPUT,...) + - pattern: "new $VM.Script(<... $REQ.$QUERY.$FOO ...>,...)" + - pattern: "new $VM.Script(<... $REQ.$BODY ...>,...)" + - pattern: | + $INPUT = <... $REQ.$QUERY.$FOO ...>; + ... + new $VM.Script($INPUT,...) + - pattern: | + $INPUT = <... $REQ.$BODY ...>; + ... + new $VM.Script($INPUT,...) + message: | + Untrusted user input reaching `vm` can result in code injection. + severity: "ERROR" + languages: + - "javascript" + metadata: + cwe: "CWE-94" + shortDescription: "Improper control of generation of code (Code Injection)" + category: "security" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "CRITICAL" +- id: rules_lgpl_javascript_eval_rule-vm-compilefunction-injection + patterns: + - pattern-inside: | + require('vm') + ... + - pattern-either: + - pattern-inside: |- + function ($REQ, $RES, ...) {...} + - pattern-inside: |- + function $FUNC($REQ, $RES, ...) {...} + - pattern-inside: |- + $X = function $FUNC($REQ, $RES, ...) {...} + - pattern-inside: |- + var $X = function $FUNC($REQ, $RES, ...) {...}; + - pattern-inside: |- + $APP.$METHOD(..., function $FUNC($REQ, $RES, ...) {...}) + - pattern-either: + - pattern: | + $VM.compileFunction($CODE,$PARAMS,{parsingContext: <... $REQ.$QUERY.$FOO ...>},...) + - pattern: | + $CONTEXT = <... $REQ.$QUERY.$FOO ...>; ... $VM.compileFunction($CODE,$PARAMS,{parsingContext: <... $CONTEXT ...>},...) + - pattern: | + $CONTEXT = <... {$NAME:$REQ.$QUERY.$FOO} ...>; ... $VM.compileFunction($CODE,$PARAMS,{parsingContext: <... $CONTEXT ...>},...) + - pattern: | + $CONTEXT = {$NAME: <... $REQ.$QUERY.$FOO ...>}; ... $VM.compileFunction($CODE,$PARAMS,{parsingContext: <... $CONTEXT ...>},...) + - pattern: | + $VAR = <... $REQ.$QUERY.$FOO ...>; ... $CONTEXT = {$NAME: <... $VAR ...>}; ... $VM.compileFunction($CODE,$PARAMS,{parsingContext: <... $CONTEXT ...>},...) + - pattern: | + $OPTS = {parsingContext: <... $REQ.$QUERY.$FOO ...>}; + ... + $VM.compileFunction($CODE,$PARAMS,$OPTS,...) + - pattern: | + $CONTEXT = <... $REQ.$QUERY.$FOO ...>; + ... + $OPTS = {parsingContext: <... $CONTEXT ...>}; + ... + $VM.compileFunction($CODE,$PARAMS,$OPTS,...) + - pattern: | + $CONTEXT = {$NAME: <... $REQ.$QUERY.$FOO ...>}; + ... + $OPTS = {parsingContext: <... $CONTEXT ...>}; + ... + $VM.compileFunction($CODE,$PARAMS,$OPTS,...) + - pattern: | + $VAR = <... $REQ.$QUERY.$FOO ...>; + ... + $CONTEXT = {$NAME: <... $VAR ...>}; + ... + $OPTS = {parsingContext: <... $CONTEXT ...>}; + ... + $VM.compileFunction($CODE,$PARAMS,$OPTS,...) + - pattern: | + $VM.compileFunction($CODE,$PARAMS,{parsingContext: <... $REQ.$BODY ...>},...) + - pattern: | + $CONTEXT = <... $REQ.$BODY ...>; ... $VM.compileFunction($CODE,$PARAMS,{parsingContext: <... $CONTEXT ...>},...) + - pattern: | + $CONTEXT = <... {$NAME:$REQ.$BODY} ...>; ... $VM.compileFunction($CODE,$PARAMS,{parsingContext: <... $CONTEXT ...>},...) + - pattern: | + $CONTEXT = {$NAME: <... $REQ.$BODY ...>}; ... $VM.compileFunction($CODE,$PARAMS,{parsingContext: <... $CONTEXT ...>},...) + - pattern: | + $VAR = <... $REQ.$BODY ...>; ... $CONTEXT = {$NAME: <... $VAR ...>}; ... $VM.compileFunction($CODE,$PARAMS,{parsingContext: <... $CONTEXT ...>},...) + - pattern: | + $OPTS = {parsingContext: <... $REQ.$BODY ...>}; + ... + $VM.compileFunction($CODE,$PARAMS,$OPTS,...) + - pattern: | + $CONTEXT = <... $REQ.$BODY ...>; + ... + $OPTS = {parsingContext: <... $CONTEXT ...>}; + ... + $VM.compileFunction($CODE,$PARAMS,$OPTS,...) + - pattern: | + $CONTEXT = {$NAME: <... $REQ.$BODY ...>}; + ... + $OPTS = {parsingContext: <... $CONTEXT ...>}; + ... + $VM.compileFunction($CODE,$PARAMS,$OPTS,...) + - pattern: | + $VAR = <... $REQ.$BODY ...>; + ... + $CONTEXT = {$NAME: <... $VAR ...>}; + ... + $OPTS = {parsingContext: <... $CONTEXT ...>}; + ... + $VM.compileFunction($CODE,$PARAMS,$OPTS,...) + message: | + Untrusted user input in `vm.compileFunction()` can result in code injection. + severity: "ERROR" + languages: + - "javascript" + metadata: + cwe: "CWE-94" + shortDescription: "Improper control of generation of code (Code Injection)" + category: "security" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "CRITICAL" +- id: rules_lgpl_javascript_eval_rule-vm-runincontext-injection + patterns: + - pattern-inside: | + require('vm') + ... + - pattern-either: + - pattern-inside: |- + function ($REQ, $RES, ...) {...} + - pattern-inside: |- + function $FUNC($REQ, $RES, ...) {...} + - pattern-inside: |- + $X = function $FUNC($REQ, $RES, ...) {...} + - pattern-inside: |- + var $X = function $FUNC($REQ, $RES, ...) {...}; + - pattern-inside: |- + $APP.$METHOD(..., function $FUNC($REQ, $RES, ...) {...}) + - pattern-either: + - pattern: | + $CONTEXT = <... $REQ.$QUERY.$FOO ...>; + ... + $VM.runInContext($CODE,<... $CONTEXT ...>,...) + - pattern: | + $CONTEXT = <... {$NAME:$REQ.$QUERY.$FOO} ...>; + ... + $VM.runInContext($CODE,<... $CONTEXT ...>,...) + - pattern: | + $CONTEXT = {$NAME: <... $REQ.$QUERY.$FOO ...>}; + ... + $VM.runInContext($CODE,<... $CONTEXT ...>,...) + - pattern: | + $VAR = <... $REQ.$QUERY.$FOO ...>; + ... + $CONTEXT = {$NAME: <... $VAR ...>}; + ... + $VM.runInContext($CODE,<... $CONTEXT ...>,...) + - pattern: | + $CONTEXT = <... $REQ.$BODY ...>; + ... + $VM.runInContext($CODE,<... $CONTEXT ...>,...) + - pattern: | + $CONTEXT = <... {$NAME:$REQ.$BODY} ...>; + ... + $VM.runInContext($CODE,<... $CONTEXT ...>,...) + - pattern: | + $CONTEXT = {$NAME: <... $REQ.$BODY ...>}; + ... + $VM.runInContext($CODE,<... $CONTEXT ...>,...) + - pattern: | + $VAR = <... $REQ.$BODY ...>; + ... + $CONTEXT = {$NAME: <... $VAR ...>}; + ... + $VM.runInContext($CODE,<... $CONTEXT ...>,...) + message: | + Untrusted user input in `vm.runInContext()` can result in code injection. + severity: "ERROR" + languages: + - "javascript" + metadata: + cwe: "CWE-94" + shortDescription: "Improper control of generation of code (Code Injection)" + category: "security" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "CRITICAL" +- id: rules_lgpl_javascript_eval_rule-vm-runinnewcontext-injection + patterns: + - pattern-inside: | + require('vm') + ... + - pattern-either: + - pattern-inside: |- + function ($REQ, $RES, ...) {...} + - pattern-inside: |- + function $FUNC($REQ, $RES, ...) {...} + - pattern-inside: |- + $X = function $FUNC($REQ, $RES, ...) {...} + - pattern-inside: |- + var $X = function $FUNC($REQ, $RES, ...) {...}; + - pattern-inside: |- + $APP.$METHOD(..., function $FUNC($REQ, $RES, ...) {...}) + - pattern-either: + - pattern: | + $VM.runInNewContext($CODE,<... $REQ.$QUERY.$FOO ...>,...) + - pattern: | + $CONTEXT = <... $REQ.$QUERY.$FOO ...>; + ... + $VM.runInNewContext($CODE,<... $CONTEXT ...>,...) + - pattern: | + $CONTEXT = {$NAME: <... $REQ.$QUERY.$FOO ...>}; + ... + $VM.runInNewContext($CODE,<... $CONTEXT ...>,...) + - pattern: | + $CONTEXT = <... {$NAME:$REQ.$QUERY.$FOO} ...>; + ... + $VM.runInNewContext($CODE,<... $CONTEXT ...>,...) + - pattern: | + $VAR = <... $REQ.$QUERY.$FOO ...>; + ... + $CONTEXT = {$NAME: <... $VAR ...>}; + ... + $VM.runInNewContext($CODE,<... $CONTEXT ...>,...) + - pattern: | + $VM.runInNewContext($CODE,<... $REQ.$BODY ...>,...) + - pattern: | + $CONTEXT = <... $REQ.$BODY ...>; + ... + $VM.runInNewContext($CODE,<... $CONTEXT ...>,...) + - pattern: | + $CONTEXT = {$NAME: <... $REQ.$BODY ...>}; + ... + $VM.runInNewContext($CODE,<... $CONTEXT ...>,...) + - pattern: | + $CONTEXT = <... {$NAME:$REQ.$BODY} ...>; + ... + $VM.runInNewContext($CODE,<... $CONTEXT ...>,...) + - pattern: | + $VAR = <... $REQ.$BODY ...>; + ... + $CONTEXT = {$NAME: <... $VAR ...>}; + ... + $VM.runInNewContext($CODE,<... $CONTEXT ...>,...) + message: | + Untrusted user input in `vm.runInNewContext()` can result in code injection. + severity: "ERROR" + languages: + - "javascript" + metadata: + cwe: "CWE-94" + shortDescription: "Improper control of generation of code (Code Injection)" + category: "security" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "CRITICAL" +- id: rules_lgpl_javascript_eval_rule-yaml-deserialize + patterns: + - pattern-either: + - pattern: | + require('js-yaml').load(...) + - pattern-inside: | + $MOD = require('js-yaml') + ... + - pattern-inside: | + import $MOD from 'js-yaml' + ... + - pattern: | + $MOD.load(...) + message: | + User controlled data in 'yaml.load()' function can result in Remote Code Injection. + languages: + - "javascript" + - "typescript" + severity: "ERROR" + metadata: + owasp: + - "A8:2017-Insecure Deserialization" + - "A08:2021-Software and Data Integrity Failures" + cwe: "CWE-502" + shortDescription: "Deserialization of Untrusted Data" + security-severity: "CRITICAL" + category: "security" +- id: rules_lgpl_javascript_exec_rule-shelljs-os-command-exec + patterns: + - pattern-inside: | + require('shelljs') + ... + - pattern-either: + - pattern-inside: |- + function ($REQ, $RES, ...) {...} + - pattern-inside: |- + function $FUNC($REQ, $RES, ...) {...} + - pattern-inside: |- + $X = function $FUNC($REQ, $RES, ...) {...} + - pattern-inside: |- + var $X = function $FUNC($REQ, $RES, ...) {...}; + - pattern-inside: |- + $APP.$METHOD(..., function $FUNC($REQ, $RES, ...) {...}) + - pattern-either: + - pattern: | + $EXEC.exec(<... $REQ.$QUERY.$VAR ...>, ...) + - pattern: | + $EXEC.exec( <... $REQ.$QUERY ...>, ...) + - pattern: | + $INP = <... $REQ.$QUERY.$VAR ...>; + ... + $EXEC.exec(<... $INP ...>, ...) + - pattern: | + $INP = <... $REQ.$QUERY ...>; + ... + $EXEC.exec(<... $INP ...>, ...) + message: | + User controlled data in 'shelljs.exec()' can result in Remote OS Command Execution. + languages: + - "javascript" + severity: "ERROR" + metadata: + shortDescription: "Improper neutralization of special elements used in an OS command + ('OS Command Injection')" + category: "security" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + cwe: "CWE-78" + security-severity: "CRITICAL" +- id: rules_lgpl_javascript_headers_rule-cookie-session-default + patterns: + - pattern-either: + - pattern-inside: | + $SESSION = require('cookie-session') + ... + - pattern-inside: | + $SESSION = require('express-session') + ... + - pattern: "$SESSION(...)" + - pattern-not-inside: |- + $SESSION(<... {name:...} ...>,...) + - pattern-not-inside: | + $OPTS = <... {name:...} ...>; + ... + $SESSION($OPTS,...) + - pattern-not-inside: | + $OPTS = ...; + ... + $OPTS.name = ...; + ... + $SESSION($OPTS,...) + message: | + Consider changing the default session cookie name. An attacker can use it to fingerprint the server and target attacks accordingly. + severity: "INFO" + languages: + - "javascript" + metadata: + owasp: + - "A2:2017-Broken Authentication" + - "A07:2021-Identification and Authentication Failures" + cwe: "CWE-522" + shortDescription: "Insufficiently protected credentials" + security-severity: "INFO" + category: "security" +- id: rules_lgpl_javascript_headers_rule-cookie-session-no-domain + patterns: + - pattern-either: + - pattern-inside: | + $SESSION = require('cookie-session') + ... + - pattern-inside: | + $SESSION = require('express-session') + ... + - pattern: "$SESSION(...)" + - pattern-not-inside: |- + $SESSION(<... {cookie:{domain:...}} ...>,...) + - pattern-not-inside: | + $OPTS = <... {cookie:{domain:...}} ...>; + ... + $SESSION($OPTS,...) + - pattern-not-inside: | + $OPTS = ...; + ... + $COOKIE = <... {domain:...} ...>; + ... + $SESSION($OPTS,...) + - pattern-not-inside: | + $OPTS = ...; + ... + $OPTS.cookie = <... {domain:...} ...>; + ... + $SESSION($OPTS,...) + - pattern-not-inside: | + $OPTS = ...; + ... + $COOKIE.domain = ...; + ... + $SESSION($OPTS,...) + - pattern-not-inside: | + $OPTS = ...; + ... + $OPTS.cookie.domain = ...; + ... + $SESSION($OPTS,...) + message: | + 'Default session middleware settings: `domain` not set. It indicates the domain of the cookie; use it to compare against the domain of the server in which the URL is being requested. If they match, then check the path attribute next.' + severity: "INFO" + languages: + - "javascript" + metadata: + owasp: + - "A2:2017-Broken Authentication" + - "A07:2021-Identification and Authentication Failures" + cwe: "CWE-522" + shortDescription: "Insufficiently protected credentials" + security-severity: "INFO" + category: "security" +- id: rules_lgpl_javascript_headers_rule-cookie-session-no-httponly + patterns: + - pattern-either: + - pattern-inside: | + $SESSION = require('cookie-session') + ... + - pattern-inside: | + $SESSION = require('express-session') + ... + - pattern-either: + - pattern-inside: |- + $SESSION(<... {cookie:{httpOnly:false}} ...>,...) + - pattern-inside: | + $OPTS = <... {cookie:{httpOnly:false}} ...>; + ... + $SESSION($OPTS,...) + - pattern-inside: | + $OPTS = ...; + ... + $COOKIE = <... {httpOnly:false} ...>; + ... + $SESSION($OPTS,...) + - pattern-inside: | + $OPTS = ...; + ... + $OPTS.cookie = <... {httpOnly:false} ...>; + ... + $SESSION($OPTS,...) + - pattern-inside: | + $OPTS = ...; + ... + $COOKIE.httpOnly = false; + ... + $SESSION($OPTS,...) + - pattern-inside: | + $OPTS = ...; + ... + $OPTS.cookie.httpOnly = false; + ... + $SESSION($OPTS,...) + message: | + 'Session middleware settings: `httpOnly` is explicitly set to false. It ensures that sensitive cookies cannot be accessed by client side JavaScript and helps to protect against cross-site scripting attacks.' + severity: "WARNING" + languages: + - "javascript" + metadata: + owasp: + - "A2:2017-Broken Authentication" + - "A07:2021-Identification and Authentication Failures" + cwe: "CWE-1004" + shortDescription: "Sensitive cookie without 'HttpOnly' flag" + security-severity: "MEDIUM" + category: "security" +- id: rules_lgpl_javascript_headers_rule-cookie-session-no-maxage + patterns: + - pattern-either: + - pattern-inside: | + $SESSION = require('cookie-session') + ... + - pattern-inside: | + $SESSION = require('express-session') + ... + - pattern: "$SESSION(...)" + - pattern-not-inside: |- + $SESSION(<... {cookie:{maxAge:...}} ...>,...) + - pattern-not-inside: | + $OPTS = <... {cookie:{maxAge:...}} ...>; + ... + $SESSION($OPTS,...) + - pattern-not-inside: | + $OPTS = ...; + ... + $COOKIE = <... {maxAge:...} ...>; + ... + $SESSION($OPTS,...) + - pattern-not-inside: | + $OPTS = ...; + ... + $OPTS.cookie = <... {maxAge:...} ...>; + ... + $SESSION($OPTS,...) + - pattern-not-inside: | + $OPTS = ...; + ... + $COOKIE.maxAge = ...; + ... + $SESSION($OPTS,...) + - pattern-not-inside: |- + $OPTS = ...; + ... + $OPTS.cookie.maxAge = ...; + ... + $SESSION($OPTS,...) + message: | + 'Session middleware settings: `maxAge` not set. Use it to set expiration date for cookies.' + severity: "INFO" + languages: + - "javascript" + metadata: + owasp: + - "A2:2017-Broken Authentication" + - "A07:2021-Identification and Authentication Failures" + cwe: "CWE-613" + shortDescription: "Insufficient session expiration" + security-severity: "INFO" + category: "security" + +- id: rules_lgpl_javascript_headers_rule-cookie-session-no-path + patterns: + - pattern-either: + - pattern-inside: | + $SESSION = require('cookie-session') + ... + - pattern-inside: | + $SESSION = require('express-session') + ... + - pattern: "$SESSION(...)" + - pattern-not-inside: |- + $SESSION(<... {cookie:{path:...}} ...>,...) + - pattern-not-inside: | + $OPTS = <... {cookie:{path:...}} ...>; + ... + $SESSION($OPTS,...) + - pattern-not-inside: | + $OPTS = ...; + ... + $COOKIE = <... {path:...} ...>; + ... + $SESSION($OPTS,...) + - pattern-not-inside: | + $OPTS = ...; + ... + $OPTS.cookie = <... {path:...} ...>; + ... + $SESSION($OPTS,...) + - pattern-not-inside: | + $OPTS = ...; + ... + $COOKIE.path = ...; + ... + $SESSION($OPTS,...) + - pattern-not-inside: | + $OPTS = ...; + ... + $OPTS.cookie.path = ...; + ... + $SESSION($OPTS,...) + message: | + 'Default session middleware settings: `path` not set. It indicates the path of the cookie; use it to compare against the request path. If this and domain match, then send the cookie in the request.' + severity: "INFO" + languages: + - "javascript" + metadata: + owasp: + - "A2:2017-Broken Authentication" + - "A07:2021-Identification and Authentication Failures" + cwe: "CWE-522" + shortDescription: "Insufficiently protected credentials" + security-severity: "INFO" + category: "security" + + +- id: rules_lgpl_javascript_headers_rule-cookie-session-no-samesite + patterns: + - pattern-either: + - pattern-inside: | + $SESSION = require('cookie-session') + ... + - pattern-inside: | + $SESSION = require('express-session') + ... + - pattern: "$SESSION(...)" + - pattern-not-inside: |- + $SESSION(<... {cookie:{sameSite:true}} ...>,...) + - pattern-not-inside: |- + $SESSION(<... {cookie:{sameSite:'lax'}} ...>,...) + - pattern-not-inside: |- + $SESSION(<... {cookie:{sameSite:'strict'}} ...>,...) + - pattern-not-inside: | + $OPTS = <... {cookie:{sameSite:true}} ...>; + ... + $SESSION($OPTS,...) + - pattern-not-inside: | + $OPTS = ...; + ... + $COOKIE = <... {sameSite:true} ...>; + ... + $SESSION($OPTS,...) + - pattern-not-inside: | + $OPTS = ...; + ... + $OPTS.cookie = <... {sameSite:true} ...>; + ... + $SESSION($OPTS,...) + - pattern-not-inside: | + $OPTS = ...; + ... + $COOKIE.sameSite = true; + ... + $SESSION($OPTS,...) + - pattern-not-inside: | + $OPTS = ...; + ... + $OPTS.cookie.sameSite = true; + ... + $SESSION($OPTS,...) + - pattern-not-inside: | + $OPTS = <... {cookie:{sameSite:'strict'}} ...>; + ... + $SESSION($OPTS,...) + - pattern-not-inside: | + $OPTS = ...; + ... + $COOKIE = <... {sameSite:'strict'} ...>; + ... + $SESSION($OPTS,...) + - pattern-not-inside: | + $OPTS = ...; + ... + $OPTS.cookie = <... {sameSite:'strict'} ...>; + ... + $SESSION($OPTS,...) + - pattern-not-inside: | + $OPTS = ...; + ... + $COOKIE.sameSite = 'strict'; + ... + $SESSION($OPTS,...) + - pattern-not-inside: | + $OPTS = ...; + ... + $OPTS.cookie.sameSite = 'strict'; + ... + $SESSION($OPTS,...) + message: | + 'Default session middleware settings: `sameSite` attribute is not configured to strict or lax. These configurations provides protection against Cross Site Request Forgery attacks.' + severity: "WARNING" + languages: + - "javascript" + metadata: + owasp: + - "A2:2017-Broken Authentication" + - "A07:2021-Identification and Authentication Failures" + cwe: "CWE-1275" + shortDescription: "Sensitive cookie with improper SameSite attribute" + security-severity: "MEDIUM" + category: "security" +- id: rules_lgpl_javascript_headers_rule-cookie-session-no-secure + patterns: + - pattern-either: + - pattern-inside: | + $SESSION = require('cookie-session') + ... + - pattern-inside: | + $SESSION = require('express-session') + ... + - pattern: "$SESSION(...)" + - pattern-not-inside: |- + $SESSION(<... {cookie:{secure:true}} ...>,...) + - pattern-not-inside: | + $OPTS = <... {cookie:{secure:true}} ...>; + ... + $SESSION($OPTS,...) + - pattern-not-inside: | + $OPTS = ...; + ... + $COOKIE = <... {secure:true} ...>; + ... + $SESSION($OPTS,...) + - pattern-not-inside: | + $OPTS = ...; + ... + $OPTS.cookie = <... {secure:true} ...>; + ... + $SESSION($OPTS,...) + - pattern-not-inside: | + $OPTS = ...; + ... + $COOKIE.secure = true; + ... + $SESSION($OPTS,...) + - pattern-not-inside: | + $OPTS = ...; + ... + $OPTS.cookie.secure = true; + ... + $SESSION($OPTS,...) + message: | + 'Default session middleware settings: `secure` not set. It ensures the browser only sends the cookie over HTTPS.' + severity: "WARNING" + languages: + - "javascript" + metadata: + owasp: + - "A2:2017-Broken Authentication" + - "A07:2021-Identification and Authentication Failures" + cwe: "CWE-614" + shortDescription: "Sensitive cookie in HTTPS session without 'Secure' attribute" + security-severity: "MEDIUM" + category: "security" +- id: rules_lgpl_javascript_headers_rule-express-cors + patterns: + - pattern-either: + - pattern-inside: |- + function ($REQ, $RES, ...) {...} + - pattern-inside: |- + function $FUNC($REQ, $RES, ...) {...} + - pattern-inside: |- + $X = function $FUNC($REQ, $RES, ...) {...} + - pattern-inside: |- + var $X = function $FUNC($REQ, $RES, ...) {...}; + - pattern-inside: |- + $APP.$METHOD(..., function $FUNC($REQ, $RES, ...) {...}) + - pattern-either: + - pattern: | + $APP.options('*', cors(...)) + - pattern: | + $RES.set("=~/access-control-allow-origin/i", '*', ...) + - pattern: | + $RES.set(..., { "=~/access-control-allow-origin/i" : '*' }, ...) + - pattern: | + $RES.header("=~/access-control-allow-origin/i", '*', ...) + - pattern: | + $RES.writeHead(..., {"=~/access-control-allow-origin/i": '*' }, ...) + message: | + Access-Control-Allow-Origin response header is set to "*". This will disable CORS Same Origin Policy restrictions. + languages: + - "javascript" + severity: "WARNING" + metadata: + owasp: + - "A6:2017-Security Misconfiguration" + - "A05:2021-Security Misconfiguration" + cwe: "CWE-346" + shortDescription: "Origin validation error" + security-severity: "MEDIUM" + category: "security" +- id: rules_lgpl_javascript_headers_rule-generic-cors + patterns: + - pattern: | + $APP.options('*', cors(...)) + message: | + Access-Control-Allow-Origin response header is set to "*". This will disable CORS Same Origin Policy restrictions. + languages: + - "javascript" + severity: "WARNING" + metadata: + owasp: + - "A6:2017-Security Misconfiguration" + - "A05:2021-Security Misconfiguration" + cwe: "CWE-346" + shortDescription: "Origin validation error" + security-severity: "MEDIUM" + category: "security" +- id: rules_lgpl_javascript_headers_rule-generic-header-injection + patterns: + - pattern-either: + - pattern-inside: |- + function ($REQ, $RES, ...) {...} + - pattern-inside: |- + function $FUNC($REQ, $RES, ...) {...} + - pattern-inside: |- + $X = function $FUNC($REQ, $RES, ...) {...} + - pattern-inside: |- + var $X = function $FUNC($REQ, $RES, ...) {...}; + - pattern-inside: |- + $APP.$METHOD(..., function $FUNC($REQ, $RES, ...) {...}) + - pattern-either: + - pattern: | + $INP = $REQ.$QUERY; + ... + $RES.set(..., <... $INP ...>, ...) + - pattern: | + $INP = $REQ.$QUERY.$VAR; + ... + $RES.set(..., <... $INP ...>, ...) + - pattern: | + $INP = $REQ.$VAR; + ... + $RES.set(..., { $X: <... $INP ...>}, ...) + - pattern: | + $INP = $REQ.$QUERY.$FOO; + ... + $RES.set(..., { $X: <... $INP ...>}, ...) + - pattern: | + $INP = $REQ.$VAR; + ... + $RES.writeHead(..., { $X: <... $INP ...> }, ...) + - pattern: | + $INP = $REQ.$QUERY.$FOO; + ... + $RES.writeHead(..., { $X: <... $INP ...> }, ...) + - pattern: | + $RES.set(..., <... $REQ.$QUERY ...>, ...) + - pattern: | + $RES.set(..., <... $REQ.$QUERY.$VAR ...>, ...) + - pattern: | + $RES.set(..., { $X: <... $REQ.$VAR ...>}, ...) + - pattern: | + $RES.set(..., { $X: <... $REQ.$QUERY.$FOO ...>}, ...) + - pattern: | + $RES.writeHead(..., { $X: <... $REQ.$VAR ...> }, ...) + - pattern: | + $RES.writeHead(..., { $X: <... $REQ.$QUERY.$FOO ...> }, ...) + message: | + Untrusted user input in response header will result in HTTP Header Injection or Response Splitting Attacks. + languages: + - "javascript" + severity: "ERROR" + metadata: + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + cwe: "CWE-644" + shortDescription: "Improper neutralization of HTTP headers for scripting syntax" + security-severity: "CRITICAL" + category: "security" +- id: rules_lgpl_javascript_headers_rule-header-xss-generic + patterns: + - pattern-either: + - pattern-inside: |- + function ($REQ, $RES, ...) {...} + - pattern-inside: |- + function $FUNC($REQ, $RES, ...) {...} + - pattern-inside: |- + $X = function $FUNC($REQ, $RES, ...) {...} + - pattern-inside: |- + var $X = function $FUNC($REQ, $RES, ...) {...}; + - pattern-inside: |- + $APP.$METHOD(..., function $FUNC($REQ, $RES, ...) {...}) + - pattern-either: + - pattern: | + $RES.header("=~/x-xss-protection/i", 0, ...) + - pattern: | + $RES.set("=~/x-xss-protection/i", 0, ...) + - pattern: | + $RES.set(..., { "=~/x-xss-protection/i" : 0 }, ...) + - pattern: | + $RES.writeHead(..., {"=~/x-xss-protection/i": 0 }, ...) + message: | + X-XSS-Protection header is set to 0. This will disable the browser's XSS Filter. + languages: + - "javascript" + severity: "WARNING" + metadata: + owasp: + - "A6:2017-Security Misconfiguration" + - "A05:2021-Security Misconfiguration" + cwe: "CWE-358" + shortDescription: "Improperly implemented security check for standard" + security-severity: "MEDIUM" + category: "security" +- id: rules_lgpl_javascript_headers_rule-header-xss-lusca + patterns: + - pattern-inside: | + $X = require('lusca') + ... + - pattern-not: | + $X.use(helmet()) + - pattern-either: + - pattern: | + $X.xssProtection(false) + - pattern: | + $X({ xssProtection: false}) + message: | + X-XSS-Protection header is set to 0. This will disable the browser's XSS Filter. + languages: + - "javascript" + severity: "WARNING" + metadata: + owasp: + - "A6:2017-Security Misconfiguration" + - "A05:2021-Security Misconfiguration" + cwe: "CWE-358" + shortDescription: "Improperly implemented security check for standard" + security-severity: "MEDIUM" + category: "security" +- id: rules_lgpl_javascript_headers_rule-helmet-feature-disabled + patterns: + - pattern-either: + - pattern: | + $HELMET(..., {frameguard: false}, ...) + - pattern: | + $HELMET(..., {contentSecurityPolicy: false}, ...) + - pattern: | + $HELMET(..., {permittedCrossDomainPolicies: false}, ...) + - pattern: | + $HELMET(..., {dnsPrefetchControl: false}, ...) + - pattern: | + $HELMET(..., {expectCt: false}, ...) + - pattern: | + $HELMET(..., {featurePolicy: false}, ...) + - pattern: | + $HELMET(..., {hsts: false}, ...) + - pattern: | + $HELMET(..., {ieNoOpen: false}, ...) + - pattern: | + $HELMET(..., {noSniff: false}, ...) + - pattern: | + $HELMET(..., {hidePoweredBy: false}, ...) + - pattern: | + $HELMET(..., {referrerPolicy: false}, ...) + - pattern: | + $HELMET(..., {xssFilter: false}, ...) + message: | + One or more Security Response header is explicitly disabled in Helmet. + languages: + - "javascript" + severity: "WARNING" + metadata: + owasp: + - "A6:2017-Security Misconfiguration" + - "A05:2021-Security Misconfiguration" + cwe: "CWE-358" + shortDescription: "Improperly implemented security check for standard" + security-severity: "MEDIUM" + category: "security" +- id: rules_lgpl_javascript_headers_rule-host-header-injection + patterns: + - pattern-either: + - pattern-inside: |- + function ($REQ, $RES, ...) {...} + - pattern-inside: |- + function $FUNC($REQ, $RES, ...) {...} + - pattern-inside: |- + $X = function $FUNC($REQ, $RES, ...) {...} + - pattern-inside: |- + var $X = function $FUNC($REQ, $RES, ...) {...}; + - pattern-inside: |- + $APP.$METHOD(..., function $FUNC($REQ, $RES, ...) {...}) + - pattern-either: + - pattern: | + $X = <... "=~/.*http[s]*:///i" + $REQ.host ...>; + - pattern: | + $X = <... "=~/.*http[s]*:///i" + $REQ["host"] ...>; + - pattern: | + $X = <... "=~/.*http[s]*:///i" + $REQ("host") ...>; + - pattern: | + $X = { $Y: <... "=~/.*http[s]*:///i" + $REQ.host ...>}; + - pattern: | + $X = { $Y: <... "=~/.*http[s]*:///i" + $REQ["host"] ...>}; + - pattern: | + $X = { $Y: <... "=~/.*http[s]*:///i" + $REQ("host") ...>}; + - pattern: | + $Z = $REQ.host; + ... + $X = <... "=~/.*http[s]*:///i" + $Z ...>; + - pattern: | + $Z = $REQ["host"]; + ... + $X = <... "=~/.*http[s]*:///i" + $Z ...>; + - pattern: | + $Z = $REQ("host") + ... + $X = <... "=~/.*http[s]*:///i" + $Z ...>; + - pattern: | + $Z = $REQ.host; + ... + $X = { $Y: <... "=~/.*http[s]*:///i" + $REQ.host ...>}; + - pattern: | + $Z = $REQ["host"]; + ... + $X = { $Y: <... "=~/.*http[s]*:///i" + $Z ...>}; + - pattern: | + $Z = $REQ("host") + ... + $X = { $Y: <... "=~/.*http[s]*:///i" + $REQ("host") ...>}; + message: | + Using untrusted Host header for generating dynamic URLs can result in web cache and or password reset poisoning. + languages: + - "javascript" + severity: "WARNING" + metadata: + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + cwe: "CWE-348" + shortDescription: "Use of less trusted source" + security-severity: "MEDIUM" + category: "security" +- id: rules_lgpl_javascript_jwt_rule-hardcoded-jwt-secret + patterns: + - pattern-either: + - pattern-inside: | + const $JWT = require("jsonwebtoken"); + ... + - pattern-inside: | + const $JOSE = require("jose"); + ... + - pattern-inside: | + import $JWT from "jsonwebtoken" + ... + - pattern-inside: | + import $JOSE from "jose" + ... + - pattern-either: + - pattern: $JWT.sign($PAYLOAD, "...", ...) + - pattern: $JWT.verify($PAYLOAD, "...", ...) + - pattern: new $JOSE.SignJWT(...). ... .sign("...") + - pattern: | + var $TOKEN = new $JOSE.SignJWT(...). ... + ... + $TOKEN. ... .sign("...") + - pattern: $JOSE.jwtVerify( $TKN, "...", ... ) + - patterns: + - pattern-either: + - patterns: + - pattern-inside: | + var $KEY = $X + ... + - pattern-either: + - pattern: new $JOSE.SignJWT(...). ... .sign($KEY) + - patterns: + - pattern: | + var $TOKEN = new $JOSE.SignJWT(...). ... + ... + $TOKEN. ... .sign($KEY) + - pattern: $TOKEN. ... .sign($KEY) + - pattern: $JOSE.jwtVerify( $TKN, $KEY, ... ) + - pattern: new $JOSE.SignJWT(...). ... .sign($X) + - patterns: + - pattern: | + var $TOKEN = new $JOSE.SignJWT(...). ... + ... + $TOKEN. ... .sign($X) + - pattern: $TOKEN. ... .sign($X) + - pattern: $JOSE.jwtVerify( $TKN, $X, ... ) + - metavariable-pattern: + metavariable: $X + pattern-either: + - pattern: new TextEncoder().encode( "...",... ) + - pattern: Uint8Array.from("...", ...) + message: | + Hardcoded JWT secret or private key was found. Hardcoding secrets like JWT signing keys poses a significant security risk. + If the source code ends up in a public repository or is compromised, the secret is exposed. Attackers could then use the secret to + generate forged tokens and access the system. Store it properly in an environment variable. + + Here are some recommended safe ways to access JWT secrets: + - Use environment variables to store the secret and access it in code instead of hardcoding. This keeps it out of source control. + - Use a secrets management service to securely store and tightly control access to the secret. Applications can request the secret at runtime. + - For local development, use a .env file that is gitignored and access the secret from process.env. + + sample code snippet of accessing JWT secret from env variables + ``` + const token = jwt.sign(payload, process.env.SECRET, { algorithm: 'HS256' }); + ``` + languages: + - "javascript" + severity: "ERROR" + metadata: + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + cwe: "CWE-798" + shortDescription: "Use of hard-coded credentials" + security-severity: "HIGH" + category: "security" +- id: rules_lgpl_javascript_jwt_rule-jwt-exposed-credentials + patterns: + - pattern-either: + - pattern-inside: | + const $JWT = require("jsonwebtoken"); + ... + - pattern-inside: | + const $JOSE = require("jose"); + ... + - pattern-inside: | + import $JWT from "jsonwebtoken" + ... + - pattern-inside: | + import $JOSE from "jose" + ... + - pattern-either: + - pattern: "$JWT.sign(<... {$PASSWORD: $VALUE} ...>, ...)" + - patterns: + - pattern: | + $OBJ = <... {$PASSWORD: $VALUE} ...> + ... + $TOKEN = $JWT.sign(<... $OBJ ...>, ...) + - pattern: $TOKEN = $JWT.sign(<... $OBJ ...>, ...) + - patterns: + - pattern: | + $OBJ. ... .$PASSWORD = ... + ... + $TOKEN = $JWT.sign(<... $OBJ ...>, ...) + - pattern: $TOKEN = $JWT.sign(<... $OBJ ...>, ...) + - pattern: "new $JOSE.SignJWT(<... {$PASSWORD: $VALUE} ...>)" + - patterns: + - pattern: | + $OBJ = <... {$PASSWORD: $VALUE} ...> + ... + new $JOSE.SignJWT(<... $OBJ ...>) + - pattern: new $JOSE.SignJWT(<... $OBJ ...>) + - patterns: + - pattern: | + $OBJ. ... .$PASSWORD = ... + ... + new $JOSE.SignJWT(<... $OBJ ...>) + - pattern: new $JOSE.SignJWT(<... $OBJ ...>) + - metavariable-regex: + metavariable: $PASSWORD + regex: (?i)\b(?:.*password.*)\b + severity: "ERROR" + languages: + - "javascript" + metadata: + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + cwe: "CWE-522" + shortDescription: "Insufficiently protected credentials" + security-severity: "HIGH" + category: "security" + message: | + The application is storing a password in the JWT token payload. Storing + passwords in JWT token payloads is an insecure practice that can lead to + compromised credentials. + + The password transmitted in the JWT payload is not encrypted and therefore + visible to anyone who intercepts the token. It is recommended to avoid storing + sensitive information like passwords in JWTs. Instead, reference user identifiers + that map to credentials stored securely on the server.This helps to mitigate the + risk of exposing passwords through JWT tokens that could be intercepted or leaked. + + Secure code example of secure JWT signing: + ``` + router.route("/jsonwebtoken/1").get((req, res) => { + // any payload without passwords or any other sensitive data will be secure + const payload = { user_id: 123, username: 'john_doe' }; + const token = jwt.sign(payload, secretKey, { algorithm: 'HS256' }); + console.log('Generated Token:', token); + res.send({ token }) + }) + ``` +- id: rules_lgpl_javascript_jwt_rule-jwt-exposed-data + patterns: + - pattern-inside: | + require('jose') + ... + - pattern-either: + - patterns: + - pattern-inside: |- + function (...,$INPUT,...) {...} + - pattern-either: + - pattern: "$JOSE.JWT.sign($INPUT,...)" + - pattern: "$JWT.sign($INPUT,...)" + - patterns: + - pattern-inside: |- + function $F(...,$INPUT,...) {...} + - pattern-either: + - pattern: "$JOSE.JWT.sign($INPUT,...)" + - pattern: "$JWT.sign($INPUT,...)" + message: | + The object is passed strictly to jose.JWT.sign(...). Make sure that sensitive information is not exposed through JWT token payload. + severity: "WARNING" + metadata: + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + cwe: "CWE-522" + shortDescription: "Insufficiently protected credentials" + security-severity: "HIGH" + category: "security" + languages: + - "javascript" +- id: rules_lgpl_javascript_jwt_rule-jwt-express-hardcoded + patterns: + - pattern-either: + - pattern-inside: | + import { ..., $JWT,... } from 'express-jwt'; + ... + - pattern-inside: | + var {..., expressjwt: $JWT,... } = require('express-jwt'); + ... + - pattern-either: + - pattern: $JWT(<...{...,secret:"...",...}...>) + - patterns: + - pattern-inside: | + $OPTS = <... {secret: "..."} ...>; + ... + - pattern: "$JWT(<... $OPTS ...>,...)" + - patterns: + - pattern-inside: | + $OPTS = <... {secret: "..."} ...>; + ... + $OPTS2 = <... $OPTS ...>; + ... + - pattern: "$JWT(<... $OPTS2 ...>,...)" + message: | + Hardcoded JWT secret or private key was found. Hardcoding secrets like JWT signing keys poses a significant security risk. + If the source code ends up in a public repository or is compromised, the secret is exposed. Attackers could then use the secret to + generate forged tokens and access the system. Store it properly in an environment variable. + + Here are some recommended safe ways to access JWT secrets: + - Use environment variables to store the secret and access it in code instead of hardcoding. This keeps it out of source control. + - Use a secrets management service to securely store and tightly control access to the secret. Applications can request the secret at runtime. + - For local development, use a .env file that is gitignored and access the secret from process.env. + + sample code snippet of accessing JWT secret from env variables + ``` + router.route("/auth-route-1").get( + jwt({ secret: process.env.secret, algorithms: ['HS256'] }), + (req, res) => { + res.send('Token is valid'); + } + ); + ``` + severity: "ERROR" + languages: + - "javascript" + metadata: + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + cwe: "CWE-522" + shortDescription: "Insufficiently protected credentials" + security-severity: "CRITICAL" + category: "security" +- id: rules_lgpl_javascript_jwt_rule-jwt-not-revoked + patterns: + - pattern-inside: | + $JWT = require('express-jwt') + ... + - pattern: "$JWT(...)" + - pattern-not-inside: |- + $JWT(<... {isRevoked:...} ...>,...) + - pattern-not-inside: |- + $OPTS = <... {isRevoked:...} ...>; + ... + $JWT($OPTS,...) + message: | + No token revoking configured for `express-jwt`. A leaked token could still be used and unable to be revoked. Consider using function as the `isRevoked` option. + severity: "WARNING" + languages: + - "javascript" + metadata: + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + cwe: "CWE-522" + shortDescription: "Insufficiently protected credentials" + security-severity: "HIGH" + category: "security" +- id: rules_lgpl_javascript_jwt_rule-node-jwt-none-algorithm + mode: "taint" + pattern-sources: + - pattern: $JWT = require("jsonwebtoken") + - pattern: import $JWT from "jsonwebtoken" + pattern-sinks: + - pattern: $JWT.verify($P, $X, {...,algorithms:[...,'none',...],...},...) + - pattern: $JWT.sign($P, $X, {...,algorithm:'none',...},...) + message: | + Use of `{algorithm:'none'}` detected with `jsonwebtoken`. + Using none as the algorithm for jsonwebtoken can directly impact the integrity of the information transfer through the JWT token. + Consider using a secure algorithm to sign your JWT token such as HMAC or RSA. + Some safe usage examples: + ``` + let token = jwt.sign({user:"user1"}, 'secret', {algorithm: 'HS256'}); + ``` + Using a secure algorithm can protect the integrity of the token information. + Avoid using none as the algorithm when signing jwt tokens since it can violate the integrity of the JWT information. + languages: + - "javascript" + severity: "ERROR" + metadata: + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + cwe: "CWE-327" + shortDescription: "Use of a broken or risky cryptographic algorithm" + security-severity: "CRITICAL" + category: "security" +- id: rules_lgpl_javascript_redirect_rule-express-open-redirect + mode: taint + pattern-sources: + - patterns: + - pattern-inside: | + function ($REQ, $RES, ...) {...} + - focus-metavariable: $REQ + pattern-sinks: + - pattern: | + $RES.redirect(...) + pattern-sanitizers: + - pattern-either: + - patterns: + - pattern-either: + - pattern: | + if($VALIDATION){ + ... + $RES.redirect(...) + ... + } + - pattern: | + $A = $VALIDATION + ... + if($A){ + ... + $RES.redirect(...) + ... + } + - metavariable-pattern: + metavariable: $VALIDATION + pattern-either: + - pattern: | + $AL.includes(...) + - pattern: | + $AL.indexOf(...) !== -1 + - pattern: | + $AL.find(...) !== undefined + - pattern: | + $ALS.has(...) + - patterns: + - pattern: | + $RES.redirect("$DOM" + ...) + - metavariable-regex: + metavariable: $DOM + regex: (http(s)?:\/\/.*\/) + message: | + Passing untrusted user input in `redirect()` can result in an open redirect + vulnerability. This could be abused by malicious actors to trick users into + being redirected to websites under their control to capture authentication + information. + To prevent open redirect vulnerabilities: + + - Always validate and sanitize user inputs, especially URL parameters + or query strings that may influence the flow of the application. + - Use allowlists (lists of permitted URLs) to validate redirect targets + against known, trusted URLs before performing the redirect. + - Avoid directly using user input for redirecting. If unavoidable, ensure + strict validation against an allowlist. + + Following is an example of secure validation against allowlist to prevent the vulnerability: + ``` + // Define a list of explicitly allowed URLs for redirection + const allowedUrls = [ + 'https://www.example.com/page1', + 'https://www.example.com/page2', + 'https://secure.example.com/page3' + ]; + + app.get('/redirect/:url', (req, res) => { + const url = decodeURIComponent(req.params.url); + const isAllowed = allowedUrls.includes(url); + if (isAllowed) { + // If the URL is allowed, proceed with the redirect + res.redirect(url); + } else { + res.status(400).send('Invalid redirect URL'); + } + }); + ``` + languages: + - javascript + severity: ERROR + metadata: + shortDescription: "URL redirection to untrusted site 'open redirect'" + category: "security" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + cwe: "CWE-601" + security-severity: "CRITICAL" +- id: rules_lgpl_javascript_redirect_rule-express-open-redirect2 + mode: taint + pattern-sources: + - patterns: + - pattern-inside: | + function ($REQ, $RES, ...) {...} + - focus-metavariable: $REQ + pattern-sinks: + - pattern-either: + - patterns: + - pattern-not: | + $RES.$METHOD("=~/location/i", "=~/http(s)?:\/\/.*\//" + ...) + - pattern-not-inside: | + $VAR = "=~/http(s)?:\/\/.*\//" + ...; + ... + - pattern: | + $RES.$METHOD("=~/location/i", $VAR) + - metavariable-regex: + metavariable: $METHOD + regex: (header|set|append|setHeader) + - patterns: + - pattern-not-inside: | + $V = "=~/http(s)?:\/\/.*\//" + ...; + ... + - pattern-not: + patterns: + - pattern: | + $RES.writeHead(..., { + ..., + location: $V, + ... + }) + - metavariable-pattern: + metavariable: $V + patterns: + - pattern: | + "=~/http(s)?:\/\/.*\//" + ... + - pattern: | + $RES.writeHead(..., { + ..., + location: $V, + ... + }) + - focus-metavariable: $V + - patterns: + - pattern-not: | + $RES.location("=~/http(s)?:\/\/.*\//" + ...) + - pattern-not-inside: | + $VAR = "=~/http(s)?:\/\/.*\//" + ...; + ... + - pattern: | + $RES.location($VAR) + pattern-sanitizers: + - pattern-either: + - patterns: + - pattern-either: + - pattern: | + if($VALIDATION){ + ... + } + - pattern: | + $A = $VALIDATION + ... + if($A){ + ... + } + - metavariable-pattern: + metavariable: $VALIDATION + pattern-either: + - pattern: | + $AL.includes(...) + - pattern: | + $AL.indexOf(...) !== -1 + - pattern: | + $AL.find(...) !== undefined + - pattern: | + $ALS.has(...) + message: | + Passing untrusted user input in `redirect()` can result in an open redirect + vulnerability. This could be abused by malicious actors to trick users into + being redirected to websites under their control to capture authentication + information. + To prevent open redirect vulnerabilities: + + - Always validate and sanitize user inputs, especially URL parameters + or query strings that may influence the flow of the application. + - Use allowlists (lists of permitted URLs) to validate redirect targets + against known, trusted URLs before performing the redirect. + - Avoid directly using user input for redirecting. If unavoidable, ensure + strict validation against an allowlist. + + Following is an example of secure validation against allowlist to prevent the vulnerability: + ``` + // Define a list of explicitly allowed URLs for redirection + const allowedUrls = [ + 'https://www.example.com/page1', + 'https://www.example.com/page2', + 'https://secure.example.com/page3' + ]; + + app.get('/redirect/:url', (req, res) => { + const url = decodeURIComponent(req.params.url); + const isAllowed = allowedUrls.includes(url); + if (isAllowed) { + // If the URL is allowed, proceed with the redirect + res.location(url).status(302).end(); + } else { + res.status(400).send('Invalid redirect URL'); + } + }); + ``` + languages: + - javascript + severity: ERROR + metadata: + shortDescription: "URL redirection to untrusted site 'open redirect'" + category: "security" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + cwe: "CWE-601" + security-severity: "CRITICAL" +- id: rules_lgpl_javascript_ssrf_rule-node-ssrf + mode: taint + pattern-sources: + - patterns: + - focus-metavariable: $REQ + - pattern: function ($REQ, $RES, ...) {...} + - patterns: + - focus-metavariable: $REQ + - pattern: function $FUNC($REQ, $RES, ...) {...} + pattern-sanitizers: + - patterns: + - pattern-either: + - pattern: | + if($VALIDATION){ + ... + } + - pattern: | + $A = $VALIDATION + ... + if($A){ + ... + } + - metavariable-pattern: + metavariable: $VALIDATION + pattern-either: + - pattern: | + $AL.includes(...) + - pattern: | + $AL.indexOf(...) !== -1 + - pattern: | + $AL.find(...) !== undefined + - pattern: | + $ALS.has(...) + pattern-sinks: + - patterns: + - focus-metavariable: $REQ + - pattern-either: + - pattern-inside: | + $NEEDLE = require('needle'); + ... + - pattern-inside: | + import $NEEDLE from 'needle' + ... + - pattern-either: + - pattern: $NEEDLE('$VERB', $REQ, ...) + - pattern: $NEEDLE.$VERB($REQ, ...) + - metavariable-regex: + metavariable: $VERB + regex: ^(get|put|post|patch|delete|head)$ + - patterns: + - focus-metavariable: $REQ + - pattern-either: + - pattern-inside: | + $AXIOS = require('axios'); + ... + - pattern-inside: | + import $AXIOS from 'axios' + ... + - pattern-either: + - patterns: + - metavariable-regex: + metavariable: $URL + regex: ^(url|baseURL)$ + - pattern-either: + - pattern: | + $AXIOS({ ..., $URL: $REQ, ...}) + - pattern: | + $AXIOS.create({ ..., $URL: $REQ, ...}) + - patterns: + - pattern: $AXIOS.$VERB($REQ, ...) + - metavariable-regex: + metavariable: $VERB + regex: ^(get|put|post|patch|delete|head)$ + - patterns: + - pattern: axios($REQ) + - pattern-not-inside: axios({...}) + - pattern: | + axios.defaults.baseURL = $REQ + - patterns: + - focus-metavariable: $URL + - pattern-either: + - pattern-inside: | + {..., request, ... } = require('urllib'); + ... + - pattern-inside: | + import {..., request, ... } from 'urllib' + ... + - pattern: request($URL, ...) + - patterns: + - focus-metavariable: $URL + - pattern-either: + - pattern-inside: | + {..., HttpClient, ... } = require('urllib'); + ... + - pattern-inside: | + import {..., HttpClient, ... } from 'urllib' + ... + - pattern: | + $HTTPCLIENT = new HttpClient({ + allowH2: true, + }); + ... + $HTTPCLIENT.request($URL, ...) + - patterns: + - focus-metavariable: $URL + - pattern-either: + - pattern-inside: | + $URLLIIB = require('urllib'); + ... + - pattern-inside: | + import $URLLIIB from 'urllib' + ... + - pattern: $URLLIIB.request($URL, ...) + - patterns: + - pattern-either: + - pattern-inside: | + $SA = require('superagent'); + ... + - pattern-inside: | + import $SA from 'superagent' + ... + - patterns: + - pattern: $SA.$VERB(...) + - metavariable-regex: + metavariable: $VERB + regex: ^(get|put|post|patch|delete|head)$ + - patterns: + - pattern-either: + - patterns: + - pattern: fetch($REQ,...) + - focus-metavariable: $REQ + - pattern-not: fetch(new Request(...)) + - patterns: + - pattern: fetch(new Request($REQ,...)) + - focus-metavariable: $REQ + - pattern-not-inside: | + $REQUEST_OBJ = new Request(...) + ... + fetch($REQUEST_OBJ) + - patterns: + - pattern: new Request($REQ,...) + - focus-metavariable: $REQ + - pattern-inside: | + $REQUEST_OBJ = new Request($REQ,...) + ... + fetch($REQUEST_OBJ) + - patterns: + - focus-metavariable: $REQ + - pattern-either: + - pattern-inside: | + $HTTP = require('$PKG'); + ... + - pattern-inside: | + import $HTTP from $PKG + ... + - metavariable-regex: + metavariable: $PKG + regex: ^(http|https)$ + - metavariable-regex: + metavariable: $METHOD + regex: ^(get|request)$ + - pattern-either: + - patterns: + - pattern: $HTTP.$METHOD($REQ, ...) + - pattern-not-inside: | + $HTTP.$METHOD({...}, ...) + - pattern-not-inside: | + $OPTS = {...} + ... + $HTTP.$METHOD($OPTS, ...) + - pattern: | + $HTTP.$METHOD({..., hostname: $REQ}, ...) + - pattern: | + $OPTS = {..., hostname: $REQ, ...} + ... + $HTTP.$METHOD($OPTS, ...) + - patterns: + - focus-metavariable: $REQ + - pattern-either: + - pattern-inside: | + { ..., io, ... } = require('socket.io-client'); + ... + - pattern-inside: | + import { ..., io, ... } from 'socket.io-client' + ... + - pattern: io($REQ, ...) + - patterns: + - focus-metavariable: $HOST + - pattern-either: + - pattern-inside: | + $NET = require('net'); + ... + - pattern-inside: | + import $NET from 'net' + ... + - metavariable-regex: + metavariable: $METHOD + regex: ^(connect|createConnection)$ + - pattern-either: + - pattern: $NET.$METHOD($PORT, $HOST, ...) + - pattern: | + $NET.$METHOD({..., host: $HOST, ...}, ...) + - pattern: | + $OPTS = {..., host: $HOST, ...} + ... + $NET.$METHOD($OPTS, ...) + - pattern: | + $CLIENT = new $NET.Socket() + ... + $CLIENT.$METHOD($PORT, $HOST, ...) + - patterns: + - pattern-either: + - pattern-inside: | + $BENT = require('bent'); + ... + - pattern-inside: | + import $BENT from 'bent'; + ... + - pattern: $BENT(...) + - patterns: + - focus-metavariable: $REQ + - pattern-either: + - pattern-inside: | + $BENT = require('bent'); + ... + $MTD = $BENT(...) + - pattern-inside: | + import $BENT from 'bent'; + ... + $MTD = $BENT(...) + - pattern: $MTD($REQ, ...) + - patterns: + - pattern-either: + - pattern-inside: | + $BENT = require('bent'); + ... + $GETBENT = $BENT('$PKG') + ... + - pattern-inside: | + import $BENT from 'bent'; + ... + $GETBENT = $BENT('$PKG') + ... + - pattern: $GETBENT(...) + - metavariable-regex: + metavariable: $PKG + regex: ^(json|buffer)$ + - patterns: + - focus-metavariable: $REQ + - pattern-either: + - pattern-inside: | + import $GOT from 'got'; + ... + - pattern: $GOT.$VERB($REQ, ...) + - metavariable-regex: + metavariable: $VERB + regex: ^(get|put|post|patch|delete|head)$ + - patterns: + - focus-metavariable: $URL + - pattern-either: + - pattern-inside: | + $REQUEST = require('request'); + ... + - pattern-inside: | + import $REQUEST from 'request'; + ... + - pattern: $REQUEST($URL, ...) + message: | + This application allows user-controlled URLs to be passed directly to HTTP client libraries. + This can result in Server-Side Request Forgery (SSRF). + SSRF refers to an attack where the attacker can abuse functionality on + the server to force it to make requests to other internal systems within your + infrastructure that are not directly exposed to the internet. + This allows the attacker to access internal resources they do not have direct access to. + + Some risks of SSRF are: + + - Access and manipulation of internal databases, APIs, or administrative panels + - Ability to scan internal network architecture and services + - Can be used to pivot attacks into the internal network + - Circumvent network segregation and firewall rules + + To avoid this, try using hardcoded HTTP request calls or a whitelisting object to + check whether the user input is trying to access allowed resources or not. + + Here is an example: + ``` + var whitelist = [ + "https://example.com", + "https://example.com/sample" + ] + + app.get('/ssrf/node-ssrf/axios/safe/3', function (req, res) { + if(whitelist.includes(req.query.url)){ + axios.get(url, {}) + .then(function (response) { + console.log(response); + }) + .catch(function (response) { + console.log(response); + }) + } + }); + ``` + For more information on SSRF see OWASP: + https://cheatsheetseries.owasp.org/cheatsheets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet.html + languages: + - javascript + severity: ERROR + metadata: + owasp: + - A1:2017-Injection + - A03:2021-Injection + cwe: CWE-918 + shortDescription: Server-side request forgery (SSRF) + security-severity: HIGH + category: security +- id: rules_lgpl_javascript_ssrf_rule-phantom-ssrf + patterns: + - pattern-inside: | + require('phantom') + ... + - pattern-either: + - pattern-inside: |- + function $FUNC($REQ, $RES, ...) {...} + - pattern-inside: |- + $X = function $FUNC($REQ, $RES, ...) {...} + - pattern-inside: |- + var $X = function $FUNC($REQ, $RES, ...) {...}; + - pattern-inside: |- + $APP.$METHOD(..., function $FUNC($REQ, $RES, ...) {...}) + - pattern-either: + - pattern: "$PAGE.open(<... $REQ.$QUERY.$FOO ...>,...)" + - pattern: "$PAGE.setContent(<... $REQ.$QUERY.$FOO ...>,...)" + - pattern: "$PAGE.open(<... $REQ.$BODY ...>,...)" + - pattern: "$PAGE.setContent(<... $REQ.$BODY ...>,...)" + - pattern: "$PAGE.openUrl(<... $REQ.$QUERY.$FOO ...>,...)" + - pattern: "$PAGE.openUrl(<... $REQ.$BODY ...>,...)" + - pattern: "$PAGE.evaluateJavaScript(<... $REQ.$QUERY.$FOO ...>,...)" + - pattern: "$PAGE.evaluateJavaScript(<... $REQ.$BODY ...>,...)" + - pattern: "$PAGE.property(\"content\",<... $REQ.$QUERY.$FOO ...>,...)" + - pattern: "$PAGE.property(\"content\",<... $REQ.$BODY ...>,...)" + - pattern: | + $INPUT = <... $REQ.$QUERY.$FOO ...>; + ... + $PAGE.open(<... $INPUT ...>,...) + - pattern: | + $INPUT = <... $REQ.$BODY ...>; + ... + $PAGE.open(<... $INPUT ...>,...) + - pattern: | + $INPUT = <... $REQ.$QUERY.$FOO ...>; + ... + $PAGE.setContent(<... $INPUT ...>,...) + - pattern: | + $INPUT = <... $REQ.$BODY ...>; + ... + $PAGE.setContent(<... $INPUT ...>,...) + - pattern: | + $INPUT = <... $REQ.$QUERY.$FOO ...>; + ... + $PAGE.openUrl(<... $INPUT ...>,...) + - pattern: | + $INPUT = <... $REQ.$BODY ...>; + ... + $PAGE.openUrl(<... $INPUT ...>,...) + - pattern: | + $INPUT = <... $REQ.$QUERY.$FOO ...>; + ... + $PAGE.evaluateJavaScript(<... $INPUT ...>,...) + - pattern: | + $INPUT = <... $REQ.$BODY ...>; + ... + $PAGE.evaluateJavaScript(<... $INPUT ...>,...) + - pattern: | + $INPUT = <... $REQ.$QUERY.$FOO ...>; + ... + $PAGE.property("content",<... $INPUT ...>,...) + - pattern: |- + $INPUT = <... $REQ.$BODY ...>; + ... + $PAGE.property("content",<... $INPUT ...>,...) + message: | + 'If unverified user data can reach the `phantom` methods it can result in Server-Side Request Forgery vulnerabilities. + + ' + metadata: + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + cwe: "CWE-918" + shortDescription: "Server-side request forgery (SSRF)" + security-severity: "CRITICAL" + category: "security" + severity: "ERROR" + languages: + - "javascript" +- id: rules_lgpl_javascript_ssrf_rule-playwright-ssrf + patterns: + - pattern-inside: | + require('playwright') + ... + - pattern-either: + - pattern-inside: |- + function $FUNC($REQ, $RES, ...) {...} + - pattern-inside: |- + $X = function $FUNC($REQ, $RES, ...) {...} + - pattern-inside: |- + var $X = function $FUNC($REQ, $RES, ...) {...}; + - pattern-inside: |- + $APP.$METHOD(..., function $FUNC($REQ, $RES, ...) {...}) + - pattern-either: + - pattern: "$PAGE.goto(<... $REQ.$QUERY.$FOO ...>, ...)" + - pattern: "$PAGE.goto(<... $REQ.$BODY ...>, ...)" + - pattern: "$PAGE.setContent(<... $REQ.$QUERY.$FOO ...>, ...)" + - pattern: "$PAGE.setContent(<... $REQ.$BODY ...>, ...)" + - pattern: "$PAGE.evaluate(<... $REQ.$QUERY.$FOO ...>, ...)" + - pattern: "$PAGE.evaluate(<... $REQ.$BODY ...>, ...)" + - pattern: "$PAGE.evaluate($CODE,..., <... $REQ.$QUERY.$FOO ...>, ...)" + - pattern: "$PAGE.evaluate($CODE,..., <... $REQ.$BODY ...>, ...)" + - pattern: "$PAGE.evaluateHandle(<... $REQ.$QUERY.$FOO ...>, ...)" + - pattern: "$PAGE.evaluateHandle(<... $REQ.$BODY ...>, ...)" + - pattern: "$PAGE.evaluateHandle($CODE,..., <... $REQ.$QUERY.$FOO ...>, ...)" + - pattern: "$PAGE.evaluateHandle($CODE,..., <... $REQ.$BODY ...>, ...)" + - pattern: "$PAGE.evaluateOnNewDocument(<... $REQ.$BODY ...>, ...)" + - pattern: "$PAGE.evaluateOnNewDocument(<... $REQ.$BODY.$FOO ...>, ...)" + - pattern: "$CONTEXT.addInitScript(<... $REQ.$BODY ...>,...)" + - pattern: "$CONTEXT.addInitScript(<... $REQ.$BODY.$FOO ...>,...)" + - pattern: | + $INPUT = <... $REQ.$QUERY.$FOO ...>; + ... + $PAGE.goto(<... $INPUT ...>,...) + - pattern: | + $INPUT = <... $REQ.$BODY ...>; + ... + $PAGE.goto(<... $INPUT ...>,...) + - pattern: | + $INPUT = <... $REQ.$QUERY.$FOO ...>; + ... + $PAGE.setContent(<... $INPUT ...>,...) + - pattern: | + $INPUT = <... $REQ.$BODY ...>; + ... + $PAGE.setContent(<... $INPUT ...>,...) + - pattern: | + $INPUT = <... $REQ.$QUERY.$FOO ...>; + ... + $PAGE.evaluate($CODE,..., <... $INPUT ...>,...) + - pattern: | + $INPUT = <... $REQ.$BODY ...>; + ... + $PAGE.evaluate($CODE,..., <... $INPUT ...>,...) + - pattern: | + $INPUT = <... $REQ.$QUERY.$FOO ...>; + ... + $PAGE.evaluate(<... $INPUT ...>,...) + - pattern: | + $INPUT = <... $REQ.$BODY ...>; + ... + $PAGE.evaluate(<... $INPUT ...>,...) + - pattern: | + $INPUT = <... $REQ.$QUERY.$FOO ...>; + ... + $PAGE.evaluateHandle(<... $INPUT ...>,...) + - pattern: | + $INPUT = <... $REQ.$BODY ...>; + ... + $PAGE.evaluateHandle(<... $INPUT ...>,...) + - pattern: | + $INPUT = <... $REQ.$QUERY.$FOO ...>; + ... + $PAGE.evaluateHandle($CODE,..., <... $INPUT ...>,...) + - pattern: | + $INPUT = <... $REQ.$BODY ...>; + ... + $PAGE.evaluateHandle($CODE,..., <... $INPUT ...>,...) + - pattern: | + $INPUT = <... $REQ.$QUERY.$FOO ...>; + ... + $PAGE.evaluateOnNewDocument(<... $INPUT ...>,...) + - pattern: | + $INPUT = <... $REQ.$BODY ...>; + ... + $PAGE.evaluateOnNewDocument(<... $INPUT ...>,...) + - pattern: | + $INPUT = <... $REQ.$BODY ...>; + ... + $CONTEXT.addInitScript($INPUT,...) + message: | + If unverified user data can reach the `puppeteer` methods it can result in Server-Side Request Forgery vulnerabilities. + metadata: + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + cwe: "CWE-918" + shortDescription: "Server-side request forgery (SSRF)" + security-severity: "CRITICAL" + category: "security" + severity: "ERROR" + languages: + - "javascript" +- id: rules_lgpl_javascript_ssrf_rule-puppeteer-ssrf + patterns: + - pattern-inside: | + require('puppeteer') + ... + - pattern-either: + - pattern-inside: |- + function $FUNC($REQ, $RES, ...) {...} + - pattern-inside: |- + $X = function $FUNC($REQ, $RES, ...) {...} + - pattern-inside: |- + var $X = function $FUNC($REQ, $RES, ...) {...}; + - pattern-inside: |- + $APP.$METHOD(..., function $FUNC($REQ, $RES, ...) {...}) + - pattern-either: + - pattern: "$PAGE.goto(<... $REQ.$QUERY.$FOO ...>,...)" + - pattern: "$PAGE.goto(<... $REQ.$BODY ...>,...)" + - pattern: "$PAGE.setContent(<... $REQ.$QUERY.$FOO ...>,...)" + - pattern: "$PAGE.setContent(<... $REQ.$BODY ...>,...)" + - pattern: "$PAGE.evaluate(<... $REQ.$QUERY.$FOO ...>,...)" + - pattern: "$PAGE.evaluate(<... $REQ.$BODY ...>,...)" + - pattern: "$PAGE.evaluateHandle(<... $REQ.$QUERY.$FOO ...>,...)" + - pattern: "$PAGE.evaluateHandle(<... $REQ.$BODY ...>,...)" + - pattern: "$PAGE.evaluateOnNewDocument(<... $REQ.$QUERY.$FOO ...>,...)" + - pattern: "$PAGE.evaluateOnNewDocument(<... $REQ.$BODY ...>,...)" + - pattern: "$PAGE.evaluate($CODE,<... $REQ.$QUERY.$FOO ...>,...)" + - pattern: "$PAGE.evaluate($CODE,<... $REQ.$BODY ...>,...)" + - pattern: "$PAGE.evaluateHandle($CODE,<... $REQ.$QUERY.$FOO ...>,...)" + - pattern: "$PAGE.evaluateHandle($CODE,<... $REQ.$BODY ...>,...)" + - pattern: "$PAGE.evaluateOnNewDocument($CODE,<... $REQ.$QUERY.$FOO ...>,...)" + - pattern: "$PAGE.evaluateOnNewDocument($CODE,<... $REQ.$BODY ...>,...)" + - pattern: | + $INPUT = <... $REQ.$QUERY.$FOO ...>; + ... + $PAGE.goto(<... $INPUT ...>,...) + - pattern: | + $INPUT = <... $REQ.$BODY ...>; + ... + $PAGE.goto(<... $INPUT ...>,...) + - pattern: | + $INPUT = <... $REQ.$QUERY.$FOO ...>; + ... + $PAGE.setContent(<... $INPUT ...>,...) + - pattern: | + $INPUT = <... $REQ.$BODY ...>; + ... + $PAGE.setContent(<... $INPUT ...>,...) + - pattern: | + $INPUT = <... $REQ.$QUERY.$FOO ...>; + ... + $PAGE.evaluate(<... $INPUT ...>,...) + - pattern: | + $INPUT = <... $REQ.$BODY ...>; + ... + $PAGE.evaluate(<... $INPUT ...>,...) + - pattern: | + $INPUT = <... $REQ.$QUERY.$FOO ...>; + ... + $PAGE.evaluateHandle(<... $INPUT ...>,...) + - pattern: | + $INPUT = <... $REQ.$BODY ...>; + ... + $PAGE.evaluateHandle(<... $INPUT ...>,...) + - pattern: | + $INPUT = <... $REQ.$QUERY.$FOO ...>; + ... + $PAGE.evaluateOnNewDocument(<... $INPUT ...>,...) + - pattern: | + $INPUT = <... $REQ.$BODY ...>; + ... + $PAGE.evaluateOnNewDocument(<... $INPUT ...>,...) + - pattern: | + $INPUT = <... $REQ.$QUERY.$FOO ...>; + ... + $PAGE.evaluate($CODE,<... $INPUT ...>,...) + - pattern: | + $INPUT = <... $REQ.$BODY ...>; + ... + $PAGE.evaluate($CODE,<... $INPUT ...>,...) + - pattern: | + $INPUT = <... $REQ.$QUERY.$FOO ...>; + ... + $PAGE.evaluateHandle($CODE,<... $INPUT ...>,...) + - pattern: | + $INPUT = <... $REQ.$BODY ...>; + ... + $PAGE.evaluateHandle($CODE,<... $INPUT ...>,...) + - pattern: | + $INPUT = <... $REQ.$QUERY.$FOO ...>; + ... + $PAGE.evaluateOnNewDocument($CODE,<... $INPUT ...>,...) + - pattern: | + $INPUT = <... $REQ.$BODY ...>; + ... + $PAGE.evaluateOnNewDocument($CODE,<... $INPUT ...>,...) + message: | + If unverified user data can reach the `puppeteer` methods it can result in Server-Side Request Forgery vulnerabilities. + metadata: + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + cwe: "CWE-918" + shortDescription: "Server-side request forgery (SSRF)" + security-severity: "CRITICAL" + category: "security" + severity: "ERROR" + languages: + - "javascript" +- id: rules_lgpl_javascript_ssrf_rule-wkhtmltoimage-ssrf + mode: taint + pattern-sources: + - patterns: + - pattern: | + function($REQ, $RES, ...){ + ... + } + - focus-metavariable: $REQ + pattern-sinks: + - patterns: + - pattern-either: + - pattern-inside: | + $W = require('wkhtmltoimage') + ... + - pattern-inside: | + import $W from 'wkhtmltoimage' + ... + - pattern: | + $W.generate(...) + pattern-sanitizers: + - patterns: + - pattern-inside: | + if($ALLOWED.includes($URL)){ + ... + } + message: | + This rule detects instances where user-controlled URLs are passed directly + to the `generate` function of `wkhtmltoimage` library. This practice can + lead to Server Side Request Forgery (SSRF) vulnerabilities, where an + attacker can induce the server to make requests to arbitrary URLs. This + can potentially expose internal services within the network or lead to + information disclosure. + + To mitigate this vulnerability, ensure that URLs are safe and intended for + public access. Implementing allowlists for acceptable domains or schemes can + significantly reduce the risk of SSRF. Additionally, consider using server-side + proxy services that restrict the outgoing requests to trusted domains and + resources. + + Secure Code Example: + ``` + const wkhtmltoimage = require('wkhtmltoimage'); + + // Define an allowlist of domains + const allowedDomains = ['example.com', 'trusted-source.com']; + + app.post('/generate-image', (req, res) => { + const userInputUrl = req.body.url; + const parsedUrl = new URL(userInputUrl); + + // Check if the domain is in the allowlist + if (allowedDomains.includes(parsedUrl.hostname)) { + wkhtmltoimage.generate(userInputUrl, { output: 'output.jpg' }, + function (err, stream) { + if (err) { + return res.status(500).send('Error generating image'); + } + // Send a success response or the image itself + res.status(200).send('Image generated successfully'); + }); + } else { + res.status(400).send('URL is not allowed due to security policies.'); + } + }); + ``` + languages: + - "javascript" + severity: "WARNING" + metadata: + owasp: + - "A1:2017-Injection" + - "A10:2021-Server-Side Request Forgery" + cwe: "CWE-918" + shortDescription: "Server-side request forgery (SSRF)" + security-severity: "MEDIUM" + category: "security" +- id: rules_lgpl_javascript_ssrf_rule-wkhtmltopdf-ssrf + patterns: + - pattern-inside: | + require('wkhtmltopdf') + ... + - pattern-either: + - pattern-inside: |- + function ($REQ, $RES, ...) {...} + - pattern-inside: |- + function $FUNC($REQ, $RES, ...) {...} + - pattern-inside: |- + $X = function $FUNC($REQ, $RES, ...) {...} + - pattern-inside: |- + var $X = function $FUNC($REQ, $RES, ...) {...}; + - pattern-inside: |- + $APP.$METHOD(..., function $FUNC($REQ, $RES, ...) {...}) + - pattern-either: + - pattern: | + $INP = <... $REQ.$VAR ...>; + ... + wkhtmltopdf(<... $INP ...>, ...) + - pattern: | + $INP = <... $REQ.$VAR.$FOO ...>; + ... + wkhtmltopdf(<... $INP ...>, ...) + - pattern: | + wkhtmltopdf(<... $REQ.$VAR ...>, ...) + - pattern: | + wkhtmltopdf(<... $REQ.$VAR.$FOO ...>, ...) + message: | + User controlled URL reached to `wkhtmltopdf` can result in Server Side Request Forgery (SSRF). + languages: + - "javascript" + severity: "ERROR" + metadata: + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + cwe: "CWE-918" + shortDescription: "Server-side request forgery (SSRF)" + security-severity: "CRITICAL" + category: "security" +- id: rules_lgpl_javascript_traversal_rule-admzip-path-overwrite + patterns: + - pattern-inside: | + $X = require('adm-zip') + ... + - pattern-not: | + if ($FILENAME.indexOf('..')) + - pattern-not: | + $FS.createWriteStream($PATH.join(..., $PATH.basename($FILENAME, ...))) + - pattern-not: | + $FS.writeFile($PATH.join(..., $PATH.basename($FILENAME, ...))) + - pattern-not: | + $FS.writeFileSync($PATH.join(..., $PATH.basename($FILENAME, ...))) + - pattern-either: + - pattern: "$ZIPENTZ.forEach(function $FUNC($ENTRY, ...) { $FS.createWriteStream(...) + }, ...)" + - pattern: "$ZIPENTZ.forEach(function $FUNC($ENTRY, ...) { $FS.writeFile(...) + }, ...)" + - pattern: "$ZIPENTZ.forEach(function $FUNC($ENTRY, ...) { $FS.writeFileSync(...) + }, ...)" + message: | + Insecure ZIP archive extraction using adm-zip can result in arbitrary path over write and can result in code injection. + languages: + - "javascript" + metadata: + shortDescription: "Improper limitation of a pathname to a restricted directory + ('Path Traversal')" + cwe: "CWE-22" + owasp: + - "A5:2017-Broken Access Control" + - "A01:2021-Broken Access Control" + security-severity: "MEDIUM" + category: "security" + severity: "WARNING" +- id: rules_lgpl_javascript_traversal_rule-express-lfr + mode: taint + pattern-sources: + - patterns: + - pattern-inside: function ($REQ, $RES, ...) {...} + - pattern: $REQ.$FUNC. ... + - metavariable-regex: + metavariable: $FUNC + regex: ^(body|params|query|cookies|hostname|subdomains|ip|ips|originalUrl|path)$ + pattern-sinks: + - pattern: "$RES.render(..., $VAR)" + message: | + This application is using untrusted user input in express render() function. + Rendering templates with untrusted user input enables arbitrary file read + vulnerabilities when using templating engines like Handlebars (hbs). + + An attacker can craft malicious input that traverses the filesystem and exposes sensitive files. + Consider sanitizing and validating all user input before passing it to render() to prevent arbitrary file reads. + + Sample safe use of express.render function + ``` + app.get("/traversal/2", async (req, res) => { + var indexPath = "index"; + res.render(indexPath, { title: "Index Page" }) + }); + ``` + + For more details see: + https://owasp.org/www-community/attacks/Path_Traversal + languages: + - "javascript" + severity: "WARNING" + metadata: + owasp: + - "A5:2017-Broken Access Control" + - "A01:2021-Broken Access Control" + cwe: "CWE-23" + shortDescription: "Relative path traversal" + security-severity: "MEDIUM" + category: "security" +- id: rules_lgpl_javascript_traversal_rule-express-lfr-warning + patterns: + - pattern-not-inside: | + require('hbs') + ... + - pattern-inside: | + require('express') + ... + - pattern-either: + - pattern: | + $INP = <... $REQ.$QUERY ...>; + ... + $RES.render($VIEW, <... $INP ...>) + - pattern: | + $INP = <... $REQ.$QUERY.$FOO ...>; + ... + $RES.render($VIEW, <... $INP ...>) + - pattern: "$RES.render($VIEW, <... $REQ.$QUERY.$FOO ...>)" + - pattern: "$RES.render($VIEW, <... $REQ.$BODY ...>)" + message: | + Untrusted user input in express render() function can result in arbitrary file read if hbs templating is used. + languages: + - "javascript" + severity: "WARNING" + metadata: + owasp: + - "A5:2017-Broken Access Control" + - "A01:2021-Broken Access Control" + cwe: "CWE-23" + shortDescription: "Relative path traversal" + security-severity: "MEDIUM" + category: "security" +- id: rules_lgpl_javascript_traversal_rule-generic-path-traversal + mode: taint + languages: + - "javascript" + pattern-sources: + - patterns: + - focus-metavariable: $REQ + - pattern: function ($REQ, $RES, ...) {...} + pattern-sinks: + - patterns: + - pattern-either: + - pattern-inside: | + $FS = require('fs') + ... + - pattern-inside: | + import $FS from 'fs' + ... + - pattern-either: + - pattern: $FS.createReadStream(...) + - patterns: + - pattern: $FS.readFile($REQ, ...) + - focus-metavariable: $REQ + - patterns: + - pattern: $FS.readFileSync($REQ,...) + - focus-metavariable: $REQ + - patterns: + - pattern: $FS.readFileAsync($REQ,...) + - focus-metavariable: $REQ + message: | + This application is using untrusted user input with the readFile() and + readFileSync() functions. + This can lead to directory traversal attacks, as reading files with untrusted input enables arbitrary file access. + An attacker could craft malicious input that traverses the file system and exposes sensitive files. + Please consider sanitizing and validating all user input before passing it to readFile() or readFileSync() to prevent unwanted file reads. + Here is an example of a safer usage in readFileAsync(): + ``` + app.get('/foo', function (req, res) { + var fileName = config.dirName + '/' + data; + fs.readFileAsync("fileName") + .then(function (data) { + res.download(fileName, downloadFileName); + }) + }) + ``` + For more details see: + https://owasp.org/www-community/attacks/Path_Traversal + severity: "WARNING" + metadata: + owasp: + - "A5:2017-Broken Access Control" + - "A01:2021-Broken Access Control" + cwe: "CWE-23" + shortDescription: "Relative path traversal" + security-severity: "MEDIUM" + category: "security" +- id: rules_lgpl_javascript_traversal_rule-join-resolve-path-traversal + patterns: + - pattern-inside: | + require('path') + ... + - pattern-either: + - pattern-inside: |- + function ($REQ, $RES, ...) {...} + - pattern-inside: |- + function $FUNC($REQ, $RES, ...) {...} + - pattern-inside: |- + $X = function $FUNC($REQ, $RES, ...) {...} + - pattern-inside: |- + var $X = function $FUNC($REQ, $RES, ...) {...}; + - pattern-inside: |- + $APP.$METHOD(..., function $FUNC($REQ, $RES, ...) {...}) + - pattern-either: + - pattern: "$PATH.join(...,<... $REQ.$BODY ...>,...)" + - pattern: "$PATH.join(...,<... $REQ.$QUERY.$FOO ...>,...)" + - pattern: | + $VAR = <... $REQ.$BODY ...>; + ... + $PATH.join(...,<... $VAR ...>,...) + - pattern: | + $VAR = <... $REQ.$QUERY.$FOO ...>; + ... + $PATH.join(...,<... $VAR ...>,...) + - pattern: "$PATH.resolve(...,<... $REQ.$BODY ...>,...)" + - pattern: "$PATH.resolve(...,<... $REQ.$QUERY.$FOO ...>,...)" + - pattern: | + $VAR = <... $REQ.$BODY ...>; + ... + $PATH.resolve(...,<... $VAR ...>,...) + - pattern: |- + $VAR = <... $REQ.$QUERY.$FOO ...>; + ... + $PATH.resolve(...,<... $VAR ...>,...) + message: | + 'Path constructed with user input can result in Path Traversal. Ensure that user input does not reach `join()` or `resolve()`. ' + languages: + - "javascript" + metadata: + shortDescription: "Improper limitation of a pathname to a restricted directory + ('Path Traversal')" + cwe: "CWE-22" + owasp: + - "A5:2017-Broken Access Control" + - "A01:2021-Broken Access Control" + security-severity: "MEDIUM" + category: "security" + severity: "WARNING" +- id: rules_lgpl_javascript_traversal_rule-tar-path-overwrite + patterns: + - pattern-inside: | + $X = require('tar-stream') + ... + - pattern-not-inside: | + $Y.pipe($UNZIP.Parse(...)).on('entry', function $FUNC(...) { + ... + }, ...) + - pattern-inside: | + $EXTRACT.on('entry', function $FUNC(...) { + ... + }, ...) + - pattern-not: | + if ($FILENAME.indexOf('..')) + - pattern-not: | + $FS.createWriteStream($PATH.join(..., $PATH.basename($FILENAME, ...))) + - pattern-not: | + $FS.writeFile($PATH.join(..., $PATH.basename($FILENAME, ...))) + - pattern-not: | + $FS.writeFileSync($PATH.join(..., $PATH.basename($FILENAME, ...))) + - pattern-either: + - pattern: | + $FS.createWriteStream($FIL, ...) + - pattern: | + $FS.writeFile($FIL, ...) + - pattern: | + $FS.writeFileSync($FIL, ...) + message: | + Insecure TAR archive extraction can result in arbitrary path over write and can result in code injection. + languages: + - "javascript" + severity: "WARNING" + metadata: + shortDescription: "Improper limitation of a pathname to a restricted directory + ('Path Traversal')" + cwe: "CWE-22" + owasp: + - "A5:2017-Broken Access Control" + - "A01:2021-Broken Access Control" + security-severity: "MEDIUM" + category: "security" +- id: rules_lgpl_javascript_traversal_rule-zip-path-overwrite + patterns: + - pattern-either: + - pattern-inside: | + import $X from 'unzipper' + ... + - pattern-inside: | + $X = require('unzipper') + ... + - pattern-inside: | + $Y.pipe($X.Parse(...)).on('entry', function $FUNC(...) { + ... + }, ...) + - pattern-not-inside: | + if (<... $FILENAME.indexOf(...) ...>){ + ... + } + - pattern-not-inside: | + $BASE = $PATH.basename($FILENAME, ...) + ... + $JOIN = $PATH.join(..., $BASE) + ... + - pattern-not: | + $FS.$MTD($PATH.join(..., $PATH.basename($FILENAME, ...))) + - pattern: | + $FS.$MTD($FIL, ...) + - metavariable-regex: + metavariable: $MTD + regex: ^(writeFileSync|writeFile|createWriteStream)$ + message: | + This application is extracting ZIP archives without sanitizing paths or writing files to a dedicated extraction directory. + This allows attackers to overwrite sensitive files or inject malicious code by manipulating TAR archive contents. + + To fix, sanitize all paths from ZIP archives before writing extracted files using path.basename and path.join. + + Example of extracting tar files safely: + ``` + app.get("/extract", async (req, res) => { + fs.createReadStream(zipPath) + .pipe(unzipper.Parse()) + .on('entry', entry => { + const directory = 'assets/tar/extracted/'; + const filename = entry.path; + entry.pipe(fs.createWriteStream(path.join(directory, filename))); + }); + }); + ``` + + Write extracted files only to a dedicated extraction directory, not the global filesystem. Limit extracts to allowed file type. + + See OWASP Path Traversal (https://owasp.org/www-community/attacks/Path_Traversal) and Unrestricted Upload of File with + Dangerous Type (https://owasp.org/www-community/vulnerabilities/Unrestricted_File_Upload) for more details. + languages: + - "javascript" + severity: "WARNING" + metadata: + shortDescription: "Improper limitation of a pathname to a restricted directory + ('Path Traversal')" + cwe: "CWE-22" + owasp: + - "A5:2017-Broken Access Control" + - "A01:2021-Broken Access Control" + security-severity: "MEDIUM" + category: "security" +- id: rules_lgpl_javascript_xml_rule-node-entity-expansion + patterns: + - pattern-either: + - pattern-inside: |- + function ($REQ, $RES, ...) {...} + - pattern-inside: |- + function $FUNC($REQ, $RES, ...) {...} + - pattern-inside: |- + $X = function $FUNC($REQ, $RES, ...) {...} + - pattern-inside: |- + var $X = function $FUNC($REQ, $RES, ...) {...}; + - pattern-inside: |- + $APP.$METHOD(..., function $FUNC($REQ, $RES, ...) {...}) + - pattern-either: + - pattern: | + $PARSER = new expat.Parser() + ... + $PARSER.write(..., <... $REQ.$QUERY ...>, ...) + - pattern: | + $PARSER = new expat.Parser() + ... + $PARSER.write(..., <... $REQ.$QUERY.$FOO ...>, ...) + - pattern: | + $PARSER = new expat.Parser() + ... + $PARSER.write(..., <... $REQ.$QUERY.$FOO.$FILE ...>, ...) + message: | + User controlled data in XML Parsers can result in XML Internal Entity Processing vulnerabilities like in DoS. + languages: + - "javascript" + severity: "ERROR" + metadata: + owasp: + - "A4:2017-XML External Entities (XXE)" + - "A05:2021-Security Misconfiguration" + cwe: "CWE-776" + shortDescription: "Improper restriction of recursive entity references in DTDs (XML + Entity Expansion)" + security-severity: "CRITICAL" + category: "security" +- id: rules_lgpl_javascript_xml_rule-node-xpath-injection + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - pattern: | + function ($REQ, $RES, ...) {...} + - pattern: | + function $FUNC($REQ, $RES, ...) {...} + - focus-metavariable: $REQ + pattern-sinks: + - patterns: + - pattern-either: + - pattern-inside: | + $XPATH = require('xpath') + ... + - pattern-inside: | + import { $XPATH } from 'xpath' + ... + - pattern-inside: | + import { $K as $XPATH } from 'xpath' + ... + - pattern: | + $XPATH.parse($REQ, ...) + - focus-metavariable: $REQ + pattern-sanitizers: + - patterns: + - pattern-either: + - pattern: | + if($VALIDATION){ + ... + $XPATH.parse($REQ, ...) + ... + } + - pattern: | + $A = $VALIDATION + ... + if($A){ + ... + $XPATH.parse($REQ, ...) + ... + } + - metavariable-pattern: + metavariable: $VALIDATION + pattern-either: + - pattern: | + $AL.includes(...) + - pattern: | + $AL.indexOf(...) !== -1 + - pattern: | + $AL.find(...) !== undefined + - pattern: | + $ALS.has(...) + message: | + Passing untrusted user input in `xpath.parse()` can result in XPATH injection + vulnerability. This could be abused by malicious actors to execute expressions on + on XML files to capture unauthorized information. + To prevent XPATH injection vulnerabilities: + + - Always validate and sanitize user inputs, especially parameters + or query strings that may influence the flow of the application. + - Avoid directly using user input for parsing. If unavoidable, ensure + strict validation against an allowlist. + - Use allowlists (lists of permitted expressions) to validate user input + against known, trusted expressions before performing the parse. + + + Following is an example of secure validation against allowlist to prevent the vulnerability: + ``` + // Define a list of explicitly allowed expressions for parsing + const allowedExpr = [ + 'expression1', + 'expression2', + 'expression3' + ]; + + app.get('/xml/xpath/1', (req, res) => { + var expression = req.params.exp; + var isAllowed = allowedExpr.includes(expression); + let xml_string = fs.readFileSync("books.xml", "utf8"); + var doc = new dom().parseFromString(xml_string, 'text/xml'); + if (isAllowed) { + // If the expression is allowed, proceed with the parsing + var evaluator = xpath.parse("//"+expression); + var nodes = evaluator.select({ node: doc }); + res.send(nodes[0].firstChild.data); + } else { + res.status(400).send('Invalid expression'); + } + }); + ``` + languages: + - "javascript" + severity: "ERROR" + metadata: + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + cwe: "CWE-643" + shortDescription: "Improper neutralization of data within XPath expressions (XPath Injection)" + security-severity: "CRITICAL" + category: "security" +- id: rules_lgpl_javascript_xml_rule-node-xxe + patterns: + - pattern-either: + - pattern-inside: |- + function ($REQ, $RES, ...) {...} + - pattern-inside: |- + function $FUNC($REQ, $RES, ...) {...} + - pattern-inside: |- + $X = function $FUNC($REQ, $RES, ...) {...} + - pattern-inside: |- + var $X = function $FUNC($REQ, $RES, ...) {...}; + - pattern-inside: |- + $APP.$METHOD(..., function $FUNC($REQ, $RES, ...) {...}) + - pattern-either: + - pattern: | + $LIBXML.parseXmlString(..., <... $REQ.$QUERY.$VAR.$FILE ...>, ...) + - pattern: | + $LIBXML.parseXmlString(..., <... $REQ.$QUERY.$VAR ...>, ...) + - pattern: | + $LIBXML.parseXmlString(..., <... $REQ.$QUERY ...>, ...) + - pattern: | + $FOO = <... $REQ.$QUERY.$VAR.$FILE ...>; ... $LIBXML.parseXmlString(..., <... $FOO ...>, ...) + - pattern: | + $FOO = <... $REQ.$QUERY.$VAR ...>; ... $LIBXML.parseXmlString(..., <... $FOO ...>, ...) + - pattern: | + $FOO = <... $REQ.$QUERY ...>; ... $LIBXML.parseXmlString(..., <... $FOO ...>, ...) + - pattern: | + $LIBXML.parseXml(..., <... $REQ.$QUERY.$VAR.$FILE ...>, ...) + - pattern: | + $LIBXML.parseXml(..., <... $REQ.$QUERY.$VAR ...>, ...) + - pattern: | + $LIBXML.parseXml(..., <... $REQ.$QUERY ...>, ...) + - pattern: | + $FOO = <... $REQ.$QUERY.$VAR.$FILE ...>; ... $LIBXML.parseXml(..., <... $FOO ...>, ...) + - pattern: | + $FOO = <... $REQ.$QUERY.$VAR ...>; ... $LIBXML.parseXml(..., <... $FOO ...>, ...) + - pattern: | + $FOO = <... $REQ.$QUERY ...>; + ... + $LIBXML.parseXml(..., <... $FOO ...>, ...) + - pattern: | + $PARSER = new libxmljs.SaxParser() + ... + $PARSER.parseString(..., <... $REQ.$QUERY ...>, ...) + - pattern: | + $PARSER = new libxmljs.SaxParser() + ... + $PARSER.parseString(..., <... $REQ.$QUERY.$BAR ...>, ...) + - pattern: | + $PARSER = new libxmljs.SaxParser() + ... + $PARSER.parseString(..., <... $REQ.$QUERY.$BAR.$FILE ...>, ...) + - pattern: | + $PARSER = new libxmljs.SaxPushParser() + ... + $PARSER.push(..., <... $REQ.$QUERY ...>, ...) + - pattern: | + $PARSER = new libxmljs.SaxPushParser() + ... + $PARSER.push(..., <... $REQ.$QUERY.$FOO ...> , ...) + - pattern: | + $PARSER = new libxmljs.SaxPushParser() + ... + $PARSER.push(..., <... $REQ.$QUERY.$FOO.$FILE ...> , ...) + - pattern: | + $PARSER = new libxmljs.SaxParser() + ... + $FOO = <... $REQ.$QUERY ...>; + ... + $PARSER.parseString(..., <... $FOO ...>, ...) + - pattern: | + $PARSER = new libxmljs.SaxParser() + ... + $FOO = <... $REQ.$QUERY.$BAR ...>; + ... + $PARSER.parseString(..., <... $FOO ...>, ...) + - pattern: | + $PARSER = new libxmljs.SaxParser() + ... + $FOO = <... $REQ.$QUERY.$BAR.$FILE ...>; + ... + $PARSER.parseString(..., <... $FOO ...>, ...) + - pattern: | + $PARSER = new libxmljs.SaxPushParser() + ... + $FOO = <... $REQ.$QUERY ...>; + ... + $PARSER.push(..., <... $FOO ...>, ...) + - pattern: | + $PARSER = new libxmljs.SaxPushParser() + ... + $FOO = <... $REQ.$QUERY.$BAR ...>; + ... + $PARSER.push(..., <... $FOO ...> , ...) + - pattern: | + $PARSER = new libxmljs.SaxPushParser() + ... + $FOO = <... $REQ.$QUERY.$BAR.$FILE ...>; + ... + $PARSER.push(..., <... $FOO ...> , ...) + message: | + User controlled data in XML parsers can result in XML External or Internal Entity (XXE) Processing vulnerabilities + languages: + - "javascript" + severity: "ERROR" + metadata: + owasp: + - "A4:2017-XML External Entities (XXE)" + - "A05:2021-Security Misconfiguration" + cwe: "CWE-611" + shortDescription: "Improper restriction of XML external entity reference" + security-severity: "CRITICAL" + category: "security" +- id: rules_lgpl_javascript_xml_rule-xxe-expat + patterns: + - pattern-inside: | + require('node-expat') + ... + - pattern-either: + - pattern-inside: |- + function $FUNC($REQ, $RES, ...) {...} + - pattern-inside: |- + $X = function $FUNC($REQ, $RES, ...) {...} + - pattern-inside: |- + var $X = function $FUNC($REQ, $RES, ...) {...}; + - pattern-inside: |- + $APP.$METHOD(..., function $FUNC($REQ, $RES, ...) {...}) + - pattern-either: + - pattern-inside: | + $PARSER = new $EXPAT.Parser(...) + ... + - pattern-inside: | + $PARSER = new Parser(...) + ... + - pattern-either: + - pattern: "$PARSER.parse(<... $REQ.$QUERY.$FOO ...>,...)" + - pattern: "$PARSER.parse(<... $REQ.$BODY ...>,...)" + - pattern: | + $INPUT = <... $REQ.$QUERY.$FOO ...>; + ... + $PARSER.parse(<... $INPUT ...>,...) + - pattern: | + $INPUT = <... $REQ.$BODY ...>; + ... + $PARSER.parse(<... $INPUT ...>,...) + - pattern: "$PARSER.write(<... $REQ.$QUERY.$FOO ...>,...)" + - pattern: "$PARSER.write(<... $REQ.$BODY ...>,...)" + - pattern: | + $INPUT = <... $REQ.$QUERY.$FOO ...>; + ... + $PARSER.write(<... $INPUT ...>,...) + - pattern: |- + $INPUT = <... $REQ.$BODY ...>; + ... + $PARSER.write(<... $INPUT ...>,...) + message: | + Make sure that unverified user data can not reach the XML Parser, as it can result in XML External or Internal Entity (XXE) Processing vulnerabilities. + metadata: + owasp: + - "A4:2017-XML External Entities (XXE)" + - "A05:2021-Security Misconfiguration" + cwe: "CWE-611" + shortDescription: "Improper restriction of XML external entity reference" + security-severity: "CRITICAL" + category: "security" + severity: "ERROR" + languages: + - "javascript" +- id: rules_lgpl_javascript_xss_rule-express-xss + mode: taint + options: + taint_unify_mvars: true + pattern-sources: + - patterns: + - patterns: + - metavariable-regex: + metavariable: $LIB + regex: (? { + var name = encodeURI(req.query.name); + res.send(name); + }) + ``` + + XSS is an attack that exploits a web application or system to treat user input as markup or script code. + It is important to encode the data depending on the specific context in which it is used. + languages: + - "javascript" + severity: "WARNING" + metadata: + shortDescription: "Improper neutralization of input during web page generation + ('Cross-site Scripting')" + category: "security" + cwe: "CWE-79" + owasp: + - "A7:2017-Cross-Site Scripting (XSS)" + - "A03:2021-Injection" + security-severity: "MEDIUM" +- id: rules_lgpl_javascript_xss_rule-handlebars-noescape + mode: taint + pattern-sources: + - patterns: + - focus-metavariable: $REQ + - pattern: function ($REQ, $RES, ...) {...} + - pattern-either: + - pattern-inside: | + $HB = require('handlebars'); + ... + - pattern-inside: | + import $HB from "handlebars"; + pattern-sinks: + - pattern: "$HB.compile(..., {noEscape: true,...}, ...)(...)" + - pattern: | + var $METHOD = $HB.compile(..., {noEscape: true,...}, ...) + ... + $METHOD(...) + message: | + This application is compiling strings with `Handlebars.compile` using an insecure + option of `{noEscape: true}`. This configuration bypasses the default behavior of + Handlebars, which is to escape input values to prevent Cross-Site Scripting (XSS) + attacks. + XSS attacks are a type of security breach that occurs when an attacker manages to + inject malicious scripts into web pages viewed by other users. These scripts can then + execute in the context of the victim's session, allowing the attacker to bypass access + controls and potentially access sensitive information or perform actions on behalf of the + user. It is important to encode the data depending on the specific context it is used in. + + By default, `Handlebars.compile` escapes input values to prevent XSS attacks. + Consider using `Handlebars.compile` with default settings or set `{noEscape: false}` + to force encoding of input data. + + Example of using Handlebars.compile safely: + ``` + var template = "This is {{target}}"; + var out = Handlebars.compile(template)({target: req.query.message}); + res.send(out); + ``` + languages: + - "javascript" + severity: "WARNING" + metadata: + owasp: + - "A7:2017-Cross-Site Scripting (XSS)" + - "A03:2021-Injection" + shortDescription: "Improper neutralization of script-related HTML tags in a web page + (basic XSS)" + cwe: "CWE-80" + security-severity: "MEDIUM" + category: "security" +- id: rules_lgpl_javascript_xss_rule-handlebars-safestring + mode: taint + pattern-sources: + - patterns: + - focus-metavariable: $REQ + - pattern: function ($REQ, $RES, ...) {...} + pattern-sinks: + - pattern-either: + - patterns: + - pattern-inside: | + $HB = require('handlebars') + ... + - pattern: "new $HB.SafeString(...)" + - patterns: + - pattern-inside: | + import $HB from "handlebars"; + ... + - pattern: "new $HB.SafeString(...)" + pattern-sanitizers: + - pattern-either: + - patterns: + - pattern-inside: | + $HB = require('handlebars') + ... + - pattern: "$HB.escapeExpression(...)" + - patterns: + - pattern-inside: | + import $HB from "handlebars"; + ... + - pattern: "$HB.escapeExpression(...)" + message: | + This application is using a vulnerable method `Handlebars.SafeString(...)`. + Handlebars SafeString method does not escape the data passed through it. + Untrusted user input passing through SafeString method can make the application + vulnerable to Cross-Site Scripting (XSS) attacks. + + XSS attacks are a type of security breach that occurs when an attacker manages to + inject malicious scripts into web pages viewed by other users. These scripts can then + execute in the context of the victim's session, allowing the attacker to bypass access + controls and potentially access sensitive information or perform actions on behalf of the + user. It is important to encode the data depending on the specific context it is used in. + + Consider using the `Handlebars.escapeExpression` method to escape user input while + constructing SafeString to avoid potential security concerns. Following is a secure code + example. + ``` + var returnObj = new Handlebars.SafeString("

    Handlebars safe string

    " + Handlebars.escapeExpression(req.query.message)) + res.send(returnObj.string) + ``` + languages: + - "javascript" + severity: "WARNING" + metadata: + owasp: + - "A7:2017-Cross-Site Scripting (XSS)" + - "A03:2021-Injection" + cwe: "CWE-79" + shortDescription: "Improper neutralization of input during web page generation (Cross-site Scripting)" + security-severity: "MEDIUM" + category: "security" +- id: rules_lgpl_javascript_xss_rule-squirrelly-autoescape + pattern-either: + - patterns: + - pattern-inside: | + $SQLY = require('squirrelly') + ... + - pattern: "$SQLY.autoEscaping(false)" + - patterns: + - pattern-inside: | + import $SQLY from 'squirrelly'; + ... + - pattern: "$SQLY.autoEscaping(false)" + message: | + This application is rendering HTML with vulnerable + configurations by setting Sqrl.autoEscaping(false) in squirrelly. + + This could lead to Cross Site Scripting (XSS) if the input is malicious + script code and the application server is not properly validating the output. + + ``` + // safe use of squirrelly render + var myTemplate = "

    My Message is: {{message}}

    " + Sqrl.Render(myTemplate, {message: req.query.message}) + ``` + + XSS is an attack that exploits a web application or system to treat user input as markup or script code. + It is important to encode the data depending on the specific context it is used in. + + By default, squirrelly autoEscaping(true) escapes input values to prevent XSS attacks. + Consider using squirrelly with default autoEscaping settings. + languages: + - "javascript" + severity: "WARNING" + metadata: + shortDescription: "Improper neutralization of input during web page generation + ('Cross-site Scripting')" + category: "security" + cwe: "CWE-79" + owasp: + - "A7:2017-Cross-Site Scripting (XSS)" + - "A03:2021-Injection" + security-severity: "MEDIUM" +- id: rules_lgpl_javascript_xss_rule-xss-disable-mustache-escape + pattern: "$OBJ.escapeMarkup = false" + severity: "WARNING" + languages: + - "javascript" + metadata: + owasp: + - "A7:2017-Cross-Site Scripting (XSS)" + - "A03:2021-Injection" + cwe: "CWE-116" + shortDescription: "Improper encoding or escaping of output" + security-severity: "MEDIUM" + category: "security" + message: | + Markup escaping disabled. This can be used with some template engines to escape disabling of HTML entities, which can lead to XSS attacks. +- id: rules_lgpl_javascript_xss_rule-xss-serialize-javascript + pattern-either: + - patterns: + - pattern-inside: | + $S = require('serialize-javascript') + ... + - pattern: "$S(..., {...,unsafe: true,...})" + - patterns: + - pattern-inside: | + import serialize from "serialize-javascript"; + ... + - pattern: "serialize(..., {...,unsafe: true,...})" + message: | + This application is serializing Javascript objects with vulnerable + configurations by setting `{unsafe: true}` in serialize-javascript. + + This could lead to Cross Site Scripting (XSS) if the input was malicious + script code and the application server is not properly validating the output. + + ``` + // safe use of serialize-javascript + const jsObj = serialize({ + foo: htmlResponse + } + ); + ``` + + XSS is an attack which exploits a web application or system to treat user input as markup or script code. + It is important to encode the data depending on the specific context it is used in. + + By default, serialize-javascript encodes input values to prevent XSS attacks. + Consider using serialize-javascript with default settings or set `{unsafe: false}` to encode + input data. + severity: "WARNING" + languages: + - "javascript" + metadata: + owasp: + - "A7:2017-Cross-Site Scripting (XSS)" + - "A03:2021-Injection" + shortDescription: "Improper neutralization of script-related HTML tags in a web page + (basic XSS)" + cwe: "CWE-80" + security-severity: "MEDIUM" + category: "security" +- id: kotlin_cookie_rule-CookieHTTPOnly + languages: + - "kotlin" + message: | + A new cookie is created without the HttpOnly flag set. The HttpOnly flag is a directive to the + browser to make sure that the cookie can not be red by malicious script. When a user is the + target of a "Cross-Site Scripting", the attacker would benefit greatly from getting the session + id for example. + severity: "WARNING" + metadata: + shortDescription: "Sensitive cookie without 'HttpOnly' flag" + category: "security" + owasp: + - "A6:2017-Security Misconfiguration" + - "A05:2021-Security Misconfiguration" + cwe: "CWE-1004" + technology: + - "kotlin" + security-severity: "MEDIUM" + + patterns: + - pattern: | + $C = $X.servlet.http.Cookie(..., ...) + ...; + ($RESP: $X.servlet.http.HttpServletResponse).addCookie($C) + - pattern-not-inside: | + $C = $X.servlet.http.Cookie(..., ...) + ... + $C.setHttpOnly(true) + ...; + ($RESP: $X.servlet.http.HttpServletResponse).addCookie($C) +- id: kotlin_cookie_rule-CookieInsecure + languages: + - "kotlin" + message: | + "A new cookie is created without the Secure flag set. The Secure flag is a + directive to the browser to make sure that the cookie is not sent for insecure communication + (http://)" + severity: "WARNING" + metadata: + shortDescription: "Sensitive cookie in HTTPS session without 'Secure' attribute" + category: "security" + cwe: "CWE-614" + owasp: + - "A6:2017-Security Misconfiguration" + - "A05:2021-Security Misconfiguration" + technology: + - "kotlin" + security-severity: "MEDIUM" + + patterns: + - pattern: | + $C = $X.servlet.http.Cookie(..., ...) + ...; + ($RESP: $X.servlet.http.HttpServletResponse).addCookie($C) + - pattern-not-inside: | + $C = $X.servlet.http.Cookie(..., ...) + ... + $C.setSecure(true) + ...; + ($RESP: $X.servlet.http.HttpServletResponse).addCookie($C) +- id: kotlin_cookie_rule-HttpResponseSplitting + languages: + - "kotlin" + message: | + When an HTTP request contains unexpected CR and LF characters, the server may respond with an + output stream that is interpreted as two different HTTP responses (instead of one). An attacker + can control the second response and mount attacks such as cross-site scripting and cache + poisoning attacks. + severity: "WARNING" + metadata: + shortDescription: "Improper neutralization of CRLF sequences in HTTP headers ('HTTP Response Splitting')" + category: "security" + cwe: "CWE-113" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + technology: + - "kotlin" + security-severity: "MEDIUM" + + mode: "taint" + pattern-sanitizers: + - patterns: + # a string that might be empty + - metavariable-pattern: + metavariable: "$S0" + pattern-either: + - pattern: "..." + - pattern: '""' + # replace pattern should include a character class with \r and \n + - metavariable-pattern: + metavariable: "$PATTERN" + patterns: + - pattern: "..." + - pattern-regex: ".*\\[\\]?(?=[^]]*\\\\r)(?=[^]]*\\\\n)[^]]*\\]\\+" + - pattern-inside: | + $STR.replace($PATTERN, $S0) + ... + - pattern: "org.apache.commons.text.StringEscapeUtils.escapeJava(...)" + pattern-sinks: + - pattern: 'javax.servlet.http.Cookie("$KEY", ...)' + - patterns: + - pattern-inside: | + $C = javax.servlet.http.Cookie("$KEY", ...) + ... + - pattern: "$C.setValue(...)" + pattern-sources: + - pattern: "($REQ: javax.servlet.http.HttpServletRequest).getParameter(...)" + - pattern: "($REQ: javax.servlet.http.HttpServletRequest).getParameterNames()" + - pattern: "($REQ: javax.servlet.http.HttpServletRequest).getParameterValues(...)" + - pattern: "($REQ: javax.servlet.http.HttpServletRequest).getParameterMap()" + - pattern: "($REQ: javax.servlet.http.HttpServletRequest).getHeader(...)" + - pattern: "($REQ: javax.servlet.http.HttpServletRequest).getPathInfo()" +- id: kotlin_cookie_rule-RequestParamToHeader + languages: + - "kotlin" + message: | + This code directly writes an HTTP parameter to an HTTP header, which allows for a HTTP + response splitting vulnerability. See http://en.wikipedia.org/wiki/HTTP_response_splitting for + more information. + severity: "ERROR" + metadata: + shortDescription: "Improper neutralization of CRLF sequences in HTTP headers ('HTTP Response Splitting')" + category: "security" + cwe: "CWE-113" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + technology: + - "kotlin" + security-severity: "CRITICAL" + + mode: "taint" + pattern-sanitizers: + - patterns: + # a string that might be empty + - metavariable-pattern: + metavariable: "$S0" + pattern-either: + - pattern: "..." + - pattern: '""' + # replace pattern should include a character class with \r and \n + - metavariable-pattern: + metavariable: "$PATTERN" + patterns: + - pattern: "..." + - pattern-regex: ".*\\[\\]?(?=[^]]*\\\\r)(?=[^]]*\\\\n)[^]]*\\]\\+" + - pattern-inside: | + $STR.replace($PATTERN, $S0); + ... + - pattern: "org.apache.commons.text.StringEscapeUtils.unescapeJava(...);" + pattern-sinks: + - pattern: '($RES: $X.servlet.http.HttpServletResponse).setHeader("$KEY", ...);' + - pattern: '($RES: $X.servlet.http.HttpServletResponse).addHeader("$KEY", ...);' + - pattern: '($WRP: $X.servlet.http.HttpServletResponseWrapper).setHeader("$KEY", ...);' + - pattern: '($WRP: $X.servlet.http.HttpServletResponseWrapper).addHeader("$KEY", ...);' + pattern-sources: + - pattern: "($REQ: $X.servlet.http.HttpServletRequest).getParameter(...);" + - pattern: "($REQ: $X.servlet.http.HttpServletRequest).getParameterNames();" + - pattern: "($REQ: $X.servlet.http.HttpServletRequest).getParameterValues(...);" + - pattern: "($REQ: $X.servlet.http.HttpServletRequest).getParameterMap();" + - pattern: "($REQ: $X.servlet.http.HttpServletRequest).getHeader(...);" + - pattern: "($REQ: $X.servlet.http.HttpServletRequest).getPathInfo();" +- id: kotlin_cors_rule-PermissiveCORSInjection + languages: + - "kotlin" + message: | + Prior to HTML5, Web browsers enforced the Same Origin Policy which ensures that in order for + JavaScript to access the contents of a Web page, both the JavaScript and the Web page must + originate from the same domain. Without the Same Origin Policy, a malicious website could serve + up JavaScript that loads sensitive information from other websites using a client's + credentials, cull through it, and communicate it back to the attacker. HTML5 makes it possible + for JavaScript to access data across domains if a new HTTP header called + Access-Control-Allow-Origin is defined. With this header, a Web server defines which other + domains are allowed to access its domain using cross-origin requests. However, caution should + be taken when defining the header because an overly permissive CORS policy will allow a + malicious application to communicate with the victim application in an inappropriate way, + leading to spoofing, data theft, relay and other attacks. + severity: "ERROR" + metadata: + shortDescription: "Permissive cross-domain policy with untrusted domains" + cwe: "CWE-942" + category: "security" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + technology: + - "kotlin" + security-severity: "CRITICAL" + + mode: "taint" + pattern-sources: + - pattern: "($REQ: HttpServletRequest).getParameter(...)" + - pattern: "($REQ: HttpServletRequest).getHeader(...)" + - pattern: "($REQ: HttpServletRequest).getPathInfo()" + - pattern: "($REQ: HttpServletRequest).getQueryString()" + - pattern: "($REQ: HttpServletRequest).getAttribute(...)" + - pattern: "($REQ: HttpServletRequest).getSession().getAttribute(...)" + - pattern: "($REQ: HttpServletRequest).getServletContext().getAttribute(...)" + - pattern: "($REQ: HttpServletRequest).getParameterValues(...)" + - pattern: "($REQ: HttpServletRequest).getParameterNames()" + - pattern: "($REQ: HttpServletRequest).getParameterMap()" + pattern-sinks: + - patterns: + - pattern-either: + - pattern: '($RES: HttpServletResponse).setHeader("$HEADER", ...)' + - pattern: '($RES: HttpServletResponse).addHeader("$HEADER", ...)' + - metavariable-regex: + metavariable: "$HEADER" + regex: "(?i)(Access-Control-Allow-Origin)" +- id: kotlin_crypto_rule-BlowfishKeySize + languages: + - "kotlin" + message: | + A small key size makes the ciphertext vulnerable to brute force attacks. At least 128 bits of + entropy should be used when generating the key if use of Blowfish is required. + severity: "WARNING" + metadata: + category: "security" + shortDescription: "Inadequate encryption strength" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + cwe: "CWE-326" + technology: + - "kotlin" + security-severity: "MEDIUM" + + patterns: + - pattern-inside: | + $KEYGEN = javax.crypto.KeyGenerator.getInstance("Blowfish", ...); + ... + $KEYGEN.init($KEY_SIZE); + - metavariable-comparison: + comparison: "$KEY_SIZE < 128" + metavariable: "$KEY_SIZE" +- id: kotlin_crypto_rule-CipherDESInsecure + languages: + - "kotlin" + message: | + DES is considered strong ciphers for modern applications. Currently, NIST recommends the usage + of AES block ciphers instead of DES. + severity: "WARNING" + metadata: + shortDescription: "Inadequate encryption strength" + category: "security" + cwe: "CWE-326" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + technology: + - "kotlin" + security-severity: "MEDIUM" + + patterns: + - pattern-inside: |- + javax.crypto.Cipher.getInstance($TRANSFORMATION, ...) + - metavariable-regex: + metavariable: "$TRANSFORMATION" + regex: '^"DES(/|"$)' +- id: kotlin_crypto_rule-CipherDESedeInsecure + languages: + - "kotlin" + message: | + Triple DES (also known as 3DES or DESede) is considered strong ciphers for modern + applications. NIST recommends the usage of AES block ciphers instead of 3DES. + severity: "WARNING" + metadata: + shortDescription: "Use of a broken or risky cryptographic algorithm" + category: "security" + cwe: "CWE-327" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + technology: + - "kotlin" + security-severity: "MEDIUM" + + patterns: + - pattern-inside: |- + javax.crypto.Cipher.getInstance($ALG, ...) + - metavariable-regex: + metavariable: "$ALG" + regex: '(?i)^"DESede(/|"$)' +- id: kotlin_crypto_rule-CipherECBMode + languages: + - "kotlin" + message: | + An authentication cipher mode which provides better confidentiality of the encrypted data + should be used instead of Electronic Code Book (ECB) mode, which does not provide good + confidentiality. Specifically, ECB mode produces the same output for the same input each time. + This allows an attacker to intercept and replay the data. + metadata: + category: "security" + cwe: "CWE-326" + shortDescription: "Inadequate Encryption Strength" + technology: + - "kotlin" + security-severity: "CRITICAL" + severity: "ERROR" + + patterns: + - pattern: javax.crypto.Cipher.getInstance($TRANSFORMATION, ...) + - metavariable-regex: + metavariable: "$TRANSFORMATION" + regex: '^"[^/]*/ECB(/.*)?"$' +- id: kotlin_crypto_rule-CipherIntegrity + languages: + - "kotlin" + message: | + The ciphertext produced is susceptible to alteration by an adversary. This mean that the + cipher provides no way to detect that the data has been tampered with. If the ciphertext can be + controlled by an attacker, it could be altered without detection. + severity: "ERROR" + metadata: + shortDescription: "Use of a broken or risky cryptographic algorithm" + category: "security" + cwe: "CWE-327" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + technology: + - "kotlin" + security-severity: "CRITICAL" + + patterns: + - pattern: | + javax.crypto.Cipher.getInstance($TRANSFORMATION, ...) + - metavariable-pattern: + metavariable: "$TRANSFORMATION" + patterns: + # any algorithm with either no mode or CBC, OFB, CTR, or ECB and any padding + - pattern-regex: '^"[^/]*(/(CBC|OFB|CTR|ECB)(/.*)?)?"$' + # ECIES and RSA algorithms are ok + - pattern-not-regex: '^"(ECIES|RSA)(/|"$)' +- id: kotlin_crypto_rule-CipherPaddingOracle + languages: + - "kotlin" + message: | + This specific mode of CBC with PKCS5Padding is susceptible to padding oracle attacks. An + adversary could potentially decrypt the message if the system exposed the difference between + plaintext with invalid padding or valid padding. The distinction between valid and invalid + padding is usually revealed through distinct error messages being returned for each condition. + severity: "ERROR" + metadata: + shortDescription: "Use of a broken or risky cryptographic algorithm" + category: "security" + cwe: "CWE-327" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + technology: + - "java" + security-severity: "CRITICAL" + + patterns: + - pattern: |- + javax.crypto.Cipher.getInstance($TRANSFORMATION) + - metavariable-regex: + metavariable: "$TRANSFORMATION" + regex: '^"[^/]*/CBC/PKCS5Padding' + - metavariable-pattern: + metavariable: "$TRANSFORMATION" + patterns: + - pattern-not-regex: '^"(RSA|ECIES)/' +- id: kotlin_crypto_rule-CustomMessageDigest + languages: + - "kotlin" + message: | + Implementing a custom MessageDigest is error-prone. National Institute of Standards and + Technology(NIST) recommends the use of SHA-224, SHA-256, SHA-384, SHA-512, SHA-512/224, or + SHA-512/256. + severity: "WARNING" + metadata: + shortDescription: "Use of a broken or risky cryptographic algorithm" + category: "security" + cwe: "CWE-327" + owasp: + - "A6:2017-Security Misconfiguration" + - "A04:2021-Insecure Design" + technology: + - "kotlin" + security-severity: "MEDIUM" + + pattern: | + class $CLAZZ : java.security.MessageDigest(...) { + ... + } +- id: kotlin_crypto_rule-HazelcastSymmetricEncryption + languages: + - "kotlin" + message: | + The network communications for Hazelcast is configured to use a symmetric cipher (probably DES + or Blowfish). Those ciphers alone do not provide integrity or secure authentication. The use of + asymmetric encryption is preferred. + severity: "WARNING" + metadata: + shortDescription: "Inadequate encryption strength" + category: "security" + cwe: "CWE-326" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + technology: + - "kotlin" + security-severity: "MEDIUM" + + pattern: "com.hazelcast.config.SymmetricEncryptionConfig()" +- id: kotlin_crypto_rule-InsufficientKeySizeRsa + languages: + - "kotlin" + message: | + Detected an insufficient key size for DSA. NIST recommends a key size + of 2048 or higher. + metadata: + shortDescription: "Inadequate encryption strength" + category: "security" + cwe: "CWE-326" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + security-severity: "MEDIUM" + severity: "WARNING" + + patterns: + - pattern-either: + - patterns: + - pattern-inside: | + $GEN = KeyPairGenerator.getInstance($ALG, ...); + ... + - pattern-either: + - pattern: "$VAR.initialize($SIZE, ...);" + - pattern: "java.security.spec.RSAKeyGenParameterSpec($SIZE,...);" + - metavariable-comparison: + comparison: "$SIZE < 2048" + metavariable: "$SIZE" + - metavariable-regex: + metavariable: "$ALG" + regex: '"(RSA|DSA)"' +- id: kotlin_crypto_rule-NullCipher + languages: + - "kotlin" + message: | + The NullCipher implements the Cipher interface by returning ciphertext identical to the + supplied plaintext. In a few contexts, such as testing, a NullCipher may be appropriate. Avoid + using the NullCipher. Its accidental use can introduce a significant confidentiality risk. + severity: "WARNING" + metadata: + shortDescription: "Use of a broken or risky cryptographic algorithm" + category: "security" + cwe: "CWE-327" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + technology: + - "kotlin" + security-severity: "MEDIUM" + + pattern: "javax.crypto.NullCipher()" +- id: kotlin_crypto_rule-RsaNoPadding + languages: + - "kotlin" + message: | + The software uses the RSA algorithm but does not incorporate Optimal Asymmetric + Encryption Padding (OAEP), which might weaken the encryption. + metadata: + shortDescription: "Use of RSA algorithm without OAEP" + category: "security" + cwe: "CWE-780" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + security-severity: "MEDIUM" + severity: "WARNING" + + pattern-either: + - patterns: + - pattern: | + $VAR = "$ALG"; + ... + javax.crypto.Cipher.getInstance($VAR); + - metavariable-regex: + metavariable: "$ALG" + regex: ".*RSA.*NoPadding.*" + - patterns: + - pattern: "javax.crypto.Cipher.getInstance($ALG,...);" + - metavariable-regex: + metavariable: "$ALG" + regex: ".*RSA.*NoPadding.*" +- id: kotlin_crypto_rule-WeakMessageDigest + languages: + - "kotlin" + message: | + DES is considered strong ciphers for modern applications. Currently, NIST recommends the usage + of AES block ciphers instead of DES. + severity: "WARNING" + metadata: + shortDescription: "Use of a broken or risky cryptographic algorithm (SHA1/MD5)" + category: "security" + cwe: "CWE-327" + owasp: + - "A6:2017-Security Misconfiguration" + - "A04:2021-Insecure Design" + technology: + - "kotlin" + security-severity: "MEDIUM" + + patterns: + - pattern-either: + - pattern: "MessageDigest.getInstance($ALG, ...)" + - pattern: "Signature.getInstance($ALG, ...)" + - metavariable-regex: + metavariable: "$ALG" + regex: ".*(MD5|MD4|MD2|SHA1|SHA-1).*" +- id: kotlin_crypto_rule-WeakTLSProtocol + languages: + - "kotlin" + message: | + A HostnameVerifier that accept any host are often use because of certificate + reuse on many hosts. As a consequence, this is vulnerable to Man-in-the-middleattacks + attacks since the client will trust any certificate. + metadata: + shortDescription: "Improper certificate validation" + category: "security" + cwe: "CWE-295" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + security-severity: "MEDIUM" + severity: "WARNING" + + patterns: + - pattern-either: + - pattern: "org.apache.http.impl.client.DefaultHttpClient()" + - pattern: "javax.net.ssl.SSLContext.getInstance(\"SSL\")" +- id: kotlin_crypto_rule-WeakTLSProtocolVersion + languages: + - "kotlin" + message: | + The application was found enabling insecure TLS protocol versions. When enabling protocol + versions for an `SSLContext`, only the following versions should be allowed: + - TLSv1.2 + - TLSv1.3 + - DTLSv1.2 + - DTLSv1.3 + + To mitigate potential security risks, it is strongly advised to enforce TLS 1.2 as the minimum + protocol version and disallow older versions such as TLS 1.0. Do note that newer versions of + Java do not even support TLS 1.0 and will throw `NoSuchAlgorithmException`. Versions of TLS + prior to 1.2 could expose the connection to downgrade attacks, where an adversary intercepts + the + connection and alters the requested protocol version to be a less secure one. + + In many scenarios, relying on the default system configuration does not meet compliance + standards. This is due to the application being deployed across diverse systems with varying + configurations and Java versions. While the default value may be secure on modern and + up-to-date systems, it may not hold true for older systems. Consequently, it is highly + recommended to explicitly define a secure configuration in all cases. + + Example configuring an SSLContext with TLSv1.2: + ``` + // Create an SSLContext with TLSv1.2 explicitly + SSLContext tlsContext = SSLContext.getInstance("TLSv1.2"); // or TLSv1.3, DTLSv1.2, DTLSv1.3 + + // Alternatively, set the enabled protocols + SSLContext serverSslContext = SSLContext.getInstance("TLS"); + SSLEngine serverEngine = serverSslContext.createSSLEngine(); + // Calling setEnabledProtocols will override the original context's configured protocol version + serverEngine.setEnabledProtocols(new String[]{ "TLSv1.2" }); + ``` + + For more information on `SSLContext` see: + - https://docs.oracle.com/en/java/javase/11/docs/api/java.base/javax/net/ssl/SSLContext.html + + For more information on MiTM attacks see: + - https://owasp.org/www-community/attacks/Manipulator-in-the-middle_attack + metadata: + shortDescription: "Inadequate encryption strength" + category: "security" + cwe: "CWE-326" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + security-severity: "MEDIUM" + severity: "WARNING" + + patterns: + - pattern-either: + - pattern-inside: | + import javax.net.ssl.*; + ... + - pattern-inside: | + import javax.net.ssl.SSLContext; + ... + - pattern-either: + - pattern-inside: | + SSLContext.getInstance("$UNSAFE_VERSION"); + - pattern-inside: | + SSLContext.getInstance(...); + ... + $ENGINE.setEnabledProtocols(arrayOf(...,"$UNSAFE_VERSION",...)); + - pattern-not: + patterns: + - pattern-inside: | + $C = SSLContext.getInstance(...); + ... + $ENGINE.setEnabledProtocols(arrayOf(...,"$DT_GOODNESS",...)); + - metavariable-regex: + metavariable: "$DT_GOODNESS" + regex: "^D?TLSv1\\.[23]$" + - pattern-not: + patterns: + - pattern-inside: | + $C = SSLContext.getInstance(...); + ... + $E = $C.createSSLEngine() + ... + $E.enabledProtocols = arrayOf(...,"$DT_GOODNESS",...) + - metavariable-regex: + metavariable: "$DT_GOODNESS" + regex: "^DTLSv1\\.[23]$" + - metavariable-regex: + metavariable: "$UNSAFE_VERSION" + regex: "^(TLS|(D)?TLSv1.(0|1))$" +- id: kotlin_csrf_rule-SpringCSRFDisabled + languages: + - "kotlin" + message: | + The application fails to protect against Cross-Site Request Forgery (CSRF) + due to disabling Spring's CSRF protection features. + metadata: + shortDescription: "Cross-Site Request Forgery (CSRF)" + category: "security" + cwe: "CWE-352" + owasp: + - "A5:2017-Broken Access Control" + - "A01:2021-Broken Access Control" + security-severity: "MEDIUM" + severity: "WARNING" + + pattern-either: + - pattern: "($H: org.springframework.security.config.annotation.web.builders.HttpSecurity). ... .csrf().disable()" + # - pattern: "($C: org.springframework.security.config.annotation.web.configurers.CsrfConfigurer).disable()" + - pattern: "($C: CsrfConfigurer).disable()" +- id: kotlin_endpoint_rule-UnvalidatedRedirect + languages: + - "kotlin" + message: | + Unvalidated redirects occur when an application redirects a user to a + destination URL specified by a user supplied parameter that is not validated. + Such vulnerabilities can be used to facilitate phishing attacks. + metadata: + category: "security" + cwe: "CWE-601" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + shortDescription: "URL redirection to untrusted site ('Open Redirect')" + security-severity: "CRITICAL" + severity: "ERROR" + + mode: "taint" + pattern-sources: + - patterns: + - pattern: | + $URL = ($REQ: $X.servlet.http.HttpServletRequest).$M(...); + - metavariable-regex: + metavariable: "$M" + regex: "(getParameter|getCookies|getHeader|getHeaders|getHeaderNames|getPathInfo|getPathTranslated|getContextPath|getQueryString|getRemoteUser|getRequestedSessionId|getRequestURI|getRequestURL|getServletPath|getParts|getPart|getReader)" + pattern-sinks: + - pattern-either: + - pattern: | + ($RES: $X.servlet.http.HttpServletResponse).sendRedirect($URL) + - pattern: | + ($RES: $X.servlet.http.HttpServletResponse).addHeader("Location", $URL) + pattern-sanitizers: + - patterns: + - pattern-inside: | + if ($SAFE.contains($URL)){ + ... + } + - pattern-either: + - pattern: | + ($RES: $X.servlet.http.HttpServletResponse).sendRedirect($URL) + - pattern: | + ($RES: $X.servlet.http.HttpServletResponse).addHeader("Location", $URL) +- id: kotlin_endpoint_rule-WeakHostNameVerification + languages: + - "kotlin" + message: | + A HostnameVerifier that accept any host are often use because of certificate + reuse on many hosts. As a consequence, this is vulnerable to Man-in-the-middle + attacks since the client will trust any certificate. + metadata: + category: "security" + cwe: "CWE-295" + shortDescription: "Improper Certificate Validation" + security-severity: "MEDIUM" + severity: "WARNING" + + patterns: + - pattern-either: + - patterns: + - pattern-inside: | + class $V : HostnameVerifier { + ... + } + - pattern: | + fun verify(...): Boolean { + return true + } + - patterns: + - pattern-inside: | + class $V : X509TrustManager { + ... + } + - pattern-either: + - pattern: "fun checkClientTrusted(...) {}" + - pattern: "fun checkServerTrusted(...) {}" + - pattern: "fun getAcceptedIssuers(): Array? {return null}" +- id: kotlin_file_rule-FileUploadFileName + languages: + - "kotlin" + message: | + The filename provided by the FileUpload API can be tampered with by the client to reference + unauthorized files. The provided filename should be properly validated to ensure it's properly + structured, contains no unauthorized path characters (e.g., / \), and refers to an authorized + file. + metadata: + category: "security" + cwe: "CWE-22" + shortDescription: "Improper limitation of a pathname to a restricted directory ('Path Traversal')" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + technology: + - "kotlin" + security-severity: "CRITICAL" + severity: "ERROR" + + pattern-either: + - patterns: + - pattern-inside: | + $FILES = ($SFU: ServletFileUpload).parseRequest(($REQ: $X.servlet.http.HttpServletRequest?)) + ... + for($ITEM in $FILES) { + ... + } + - pattern: $ITEM.getName() + - pattern: "($PART: $X.servlet.http.Part).getSubmittedFileName()" +- id: kotlin_file_rule-FilenameUtils + languages: + - "kotlin" + message: | + A file is opened to read its content. The filename comes from an input + parameter. If an unfiltered parameter is passed to this file API, files from an + arbitrary filesystem location could be read. + metadata: + shortDescription: "Improper limitation of a pathname to a restricted directory ('Path Traversal')" + cwe: "CWE-22" + owasp: + - "A5:2017-Broken Access Control" + - "A01:2021-Broken Access Control" + security-severity: "MEDIUM" + technology: + - "kotlin" + category: "security" + severity: "WARNING" + + patterns: + - pattern-inside: | + import org.apache.commons.io.FilenameUtils + ... + - pattern-either: + - pattern: "normalize(...)" + - pattern: "getExtension(...)" + - pattern: "isExtensions(...)" + - pattern: "getName(...)" + - pattern: "getBaseName(...)" + - pattern: "org.apache.commons.io.FilenameUtils.normalize(...)" + - pattern: "org.apache.commons.io.FilenameUtils.getExtension(...)" + - pattern: "org.apache.commons.io.FilenameUtils.isExtensions(...)" + - pattern: "org.apache.commons.io.FilenameUtils.getName(...)" + - pattern: "org.apache.commons.io.FilenameUtils.getBaseName(...)" +- id: kotlin_inject_rule-CommandInjection + languages: + - "kotlin" + message: | + The highlighted API is used to execute a system command. If unfiltered input is passed to this + API, it can lead to arbitrary command execution. + severity: "WARNING" + metadata: + shortDescription: "Improper neutralization of special elements used in an OS command ('OS Command Injection')" + category: "security" + cwe: "CWE-78" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + technology: + - "kotlin" + security-severity: "MEDIUM" + + pattern-either: + - patterns: + - pattern-inside: | + fun $FUNC(..., $PARAM: String, ...) { + ... + } + - pattern-inside: | + $R = Runtime.getRuntime() + ... + - pattern-either: + - pattern: "$R.exec(<...$PARAM...>,...)" + - patterns: + - pattern-either: + - pattern: | + $CMDARR = arrayOf("$SHELL",...,<...$PARAM...>,...) + ... + $R.exec($CMDARR,...) + - pattern: '$R.exec(arrayOf("$SHELL",...,<...$PARAM...>,...), ...)' + - pattern: '$R.exec(java.util.String.format("...", ...,<...$PARAM...>,...))' + - pattern: "$R.exec(($A: String) + ($B: String))" + - metavariable-regex: + metavariable: "$SHELL" + regex: "(/.../)?(sh|bash|ksh|csh|tcsh|zsh)$" + - pattern-not: '$R.exec("...","...","...",...)' + - pattern-not: | + $R.exec(arrayOf("...","...","...",...),...) + - patterns: + - pattern-inside: | + fun $FUNC(..., $PARAM: String, ...) { + ... + } + - pattern-inside: | + $PB = ProcessBuilder() + ... + - pattern-either: + - pattern: "$PB.command(<...$PARAM...>,...)" + - patterns: + - pattern-inside: |- + $VAL = <...$PARAM...>; ... + - pattern: "$PB.command(<...$VAL...>,...)" + - patterns: + - pattern-either: + - pattern: '$PB.command("$SHELL",...,<...$PARAM...>,...)' + - pattern: | + $CMDARR = java.util.Arrays.asList("$SHELL",...,<...$PARAM...>,...) + ... + $PB.command($CMDARR,...) + - pattern: '$PB.command(java.util.Arrays.asList("$SHELL",...,<...$PARAM...>,...),...)' + - pattern: '$PB.command(java.util.String.format("...", ...,<...$PARAM...>,...))' + - pattern: "$PB.command(($A: String) + ($B: String))" + - metavariable-regex: + metavariable: "$SHELL" + regex: "(/.../)?(sh|bash|ksh|csh|tcsh|zsh)$" + - pattern-not: '$PB.command("...","...","...",...)' + - pattern-not: | + $PB.command(java.util.Arrays.asList("...","...","...",...)) +- id: kotlin_inject_rule-ELInjection + languages: + - "kotlin" + message: | + An expression is built with a dynamic value. The source of the value(s) should be verified to + avoid that unfiltered values fall into this risky code evaluation. + metadata: + category: "security" + cwe: "CWE-917" + shortDescription: "Improper neutralization of special elements used in an expression language statement ('Expression Language Injection')" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + technology: + - "kotlin" + security-severity: "MEDIUM" + severity: "WARNING" + + pattern-either: + - patterns: + - metavariable-regex: + metavariable: "$METHOD" + regex: "^create(Method|Value)Expression$" + - metavariable-pattern: + metavariable: "$EXPR" + patterns: + - pattern-not: '"..."' + - pattern: | + ($EXP: ExpressionFactory ).$METHOD(($CTX: $X.el.ELContext), $EXPR, ...) + - patterns: + - pattern: | + ($P: $X.el.ELProcessor).$METHOD(...) + - pattern-not: | + ($P: $X.el.ELProcessor).$METHOD("...", ...) + - metavariable-regex: + metavariable: "$METHOD" + regex: "^(eval|(get|set)Value)$" +- id: kotlin_inject_rule-FileDisclosure + languages: + - "kotlin" + message: | + Constructing a server-side redirect path with user input could allow an + attacker to download application binaries (including application classes or + jar files) or view arbitrary files within protected directories. + metadata: + shortDescription: "Files or directories accessible to external parties" + category: "security" + cwe: "CWE-552" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "CRITICAL" + severity: "ERROR" + + mode: "taint" + pattern-sinks: + - patterns: + - pattern: "org.springframework.web.servlet.ModelAndView($FST);" + - pattern: "$FST" + - patterns: + - pattern: "org.springframework.web.servlet.ModelAndView($FST, $SND);" + - pattern: "$FST" + - patterns: + - pattern: "org.springframework.web.servlet.ModelAndView($FST, $SND, $TRD);" + - pattern: "$FST" + - patterns: + - pattern: "org.apache.struts.action.ActionForward($FST)" + - pattern: "$FST" + - patterns: + - pattern: "org.apache.struts.action.ActionForward($FST, $SND)" + - pattern: "$FST" + - patterns: + - pattern: "org.apache.struts.action.ActionForward($FST, $SND, $TRD)" + - pattern: "$SND" + - patterns: + - pattern: "org.apache.struts.action.ActionForward($FST, $SND, $TRD)" + - pattern: "$TRD" + - patterns: + - pattern-inside: | + $ACTION = org.apache.struts.action.ActionForward(); + ... + - pattern: "$ACTION.setPath(...)" + - patterns: + - pattern-inside: | + $MVC = org.springframework.web.servlet.ModelAndView(); + ... + - pattern: "$MVC.setViewName(...);" + - patterns: + - pattern-inside: | + $REQ = $HTTP.getRequestDispatcher(...); + ... + - pattern-either: + - pattern: "$REQ.include($FST, $SND)" + - pattern: "$REQ.forward($FST, $SND)" + pattern-sources: + - pattern: "($VAR: javax.servlet.http.HttpServletRequest).getParameter(...)" +- id: kotlin_inject_rule-HttpParameterPollution + languages: + - "kotlin" + message: | + Concatenating unvalidated user input into a URL can allow an attacker to override the value of + a request parameter. Attacker may be able to override existing parameter values, inject a new + parameter or exploit variables out of a direct reach. HTTP Parameter Pollution (HPP) attacks + consist of injecting encoded query string delimiters into other existing parameters. If a web + application does not properly sanitize the user input, a malicious user may compromise the + logic of the application to perform either client-side or server-side attacks. + severity: "ERROR" + metadata: + shortDescription: "Improper neutralization of argument delimiters in a command ('Argument Injection')" + category: "security" + cwe: "CWE-88" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + technology: + - "kotlin" + security-severity: "CRITICAL" + + mode: "taint" + pattern-sources: + - pattern: "($REQ: HttpServletRequest).getParameter(...)" + pattern-sanitizers: + - pattern: "java.net.URLEncoder.encode(...)" + - pattern: "com.google.common.net.UrlEscapers.urlPathSegmentEscaper().escape(...)" + pattern-sinks: + - pattern: "org.apache.http.client.methods.HttpGet(...)" + - pattern: "org.apache.commons.httpclient.methods.GetMethod(...)" + - pattern: "($GM: org.apache.commons.httpclient.methods.GetMethod).setQueryString(...)" +- id: kotlin_inject_rule-LDAPInjection + languages: + - "kotlin" + message: | + Just like SQL, all inputs passed to an LDAP query need to be passed in safely. Unfortunately, + LDAP doesn't have prepared statement interfaces like SQL. Therefore, the primary defense + against LDAP injection is strong input validation of any untrusted data before including it in + an LDAP query. + severity: "WARNING" + metadata: + shortDescription: "Improper neutralization of special elements used in an LDAP query ('LDAP Injection')" + category: "security" + cwe: "CWE-90" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + technology: + - "kotlin" + security-severity: "MEDIUM" + + mode: "taint" + pattern-sinks: + - pattern: "javax.naming.ldap.LdapName(...)" + - pattern: "($C: javax.naming.directory.Context).lookup(...)" + - pattern: "($C: javax.naming.Context).lookup(...)" + - patterns: + - pattern-inside: |- + ($C: com.unboundid.ldap.sdk.LDAPConnection).search($QUERY, ...) + - pattern: "$QUERY" + - patterns: + - pattern-either: + - patterns: + - pattern-either: + - pattern: "$CTX.lookup(...)" + - patterns: + - pattern-inside: |- + $CTX.search($QUERY, ...) + - pattern: "$QUERY" + - patterns: + - pattern-inside: |- + $CTX.search($NAME, $FILTER, ...) + - pattern: "$FILTER" + - metavariable-pattern: + metavariable: "$CTX" + pattern-either: + - pattern: "($C: DirContext)" + - pattern: "($IDC: InitialDirContext)" + - pattern: "($LC: LdapContext)" + - pattern: "($EDC: EventDirContext)" + - pattern: "($LC: LdapCtx)" + - pattern: "($C: javax.naming.directory.DirContext)" + - pattern: "($IDC: javax.naming.directory.InitialDirContext)" + - pattern: "($LC: javax.naming.ldap.LdapContext)" + - pattern: "($EDC: javax.naming.event.EventDirContext)" + - pattern: "($LC: com.sun.jndi.ldap.LdapCtx)" + # repeat the previous rule with flow constraints on $CTX instead of type constraints + - patterns: + - pattern-either: + - pattern: "$CTX.lookup(...)" + - patterns: + - pattern-inside: |- + $CTX.search($QUERY, ...) + - pattern: "$QUERY" + - patterns: + - pattern-inside: |- + $CTX.search($NAME, $FILTER, ...) + - pattern: "$FILTER" + - pattern-inside: + pattern-either: + - pattern: "$CTX = DirContext(...);..." + - pattern: "$CTX = InitialDirContext(...);..." + - pattern: "$CTX = LdapContext(...);..." + - pattern: "$CTX = EventDirContext(...);..." + - pattern: "$CTX = LdapCtx(...);..." + - pattern: "$CTX = javax.naming.directory.DirContext(...);..." + - pattern: "$CTX = javax.naming.directory.InitialDirContext(...);..." + - pattern: "$CTX = javax.naming.ldap.LdapContext(...);..." + - pattern: "$CTX = javax.naming.event.EventDirContext(...);..." + - pattern: "$CTX = com.sun.jndi.ldap.LdapCtx(...);..." + - pattern-either: + - patterns: + - pattern-either: + - patterns: + - pattern-inside: |- + $CTX.list($QUERY, ...) + - pattern: "$QUERY" + - patterns: + - pattern-inside: |- + $CTX.lookup($QUERY, ...) + - pattern: "$QUERY" + - patterns: + - pattern-inside: |- + $CTX.search($QUERY, ...) + - pattern: "$QUERY" + - patterns: + - pattern-inside: |- + $CTX.search($NAME, $FILTER, ...) + - pattern: "$FILTER" + - metavariable-pattern: + metavariable: "$CTX" + pattern-either: + - pattern: "($LT: LdapTemplate)" + - pattern: "($LO: LdapOperations)" + - pattern: "($LT: org.springframework.ldap.core.LdapTemplate)" + - pattern: "($LO: org.springframework.ldap.core.LdapOperations)" + # again with flow constraints instead of type constraints on CTX + - patterns: + - pattern-either: + - patterns: + - pattern-inside: |- + $CTX.list($QUERY, ...) + - pattern: "$QUERY" + - patterns: + - pattern-inside: |- + $CTX.lookup($QUERY, ...) + - pattern: "$QUERY" + - patterns: + - pattern-inside: |- + $CTX.search($QUERY, ...) + - pattern: "$QUERY" + - patterns: + - pattern-inside: |- + $CTX.search($NAME, $FILTER, ...) + - pattern: "$FILTER" + - pattern-inside: + pattern-either: + - pattern: "$CTX = LdapTemplate(...);..." + - pattern: "$CTX = LdapOperations(...);..." + - pattern: "$CTX = org.springframework.ldap.core.LdapTemplate(...);..." + - pattern: "$CTX = org.springframework.ldap.core.LdapOperations(...);..." + pattern-sources: + - patterns: + - pattern-inside: | + fun $FUNC(..., $VAR: String, ...) { + ... + } + - pattern: "$VAR" + - patterns: + - pattern-inside: | + fun $FUNC(..., $X: String, ...) { + ... + $VAR = ... + $X + ... + } + - pattern: "$VAR" +- id: kotlin_inject_rule-OgnlInjection + message: | + "A expression is built with a dynamic value. The source of the value(s) should be verified to + avoid that unfiltered values fall into this risky code evaluation." + languages: + - "kotlin" + severity: "WARNING" + metadata: + shortDescription: "Expression injection (OGNL)" + category: "security" + cwe: "CWE-917" + technology: + - "kotlin" + security-severity: "MEDIUM" + + patterns: + - pattern-either: + - pattern-inside: | + fun $FUNC(..., $VAR: String, ...) { + ... + } + - pattern-inside: | + fun $FUNC(..., $VAR: Map<$K,$V>, ...) { + ... + } + - pattern-inside: | + fun $FUNC(..., $VAR: Map<$K,*>, ...) { + ... + } + - pattern-inside: | + fun $FUNC(..., $VAR: java.util.HashMap<$K,$V>, ...) { + ... + } + - pattern-either: + - pattern: "com.opensymphony.xwork2.util.TextParseUtil.translateVariables(...,$VAR, ...)" + - pattern: "com.opensymphony.xwork2.util.TextParseUtil.translateVariablesCollection(..., $VAR, ...)" + - pattern: "com.opensymphony.xwork2.util.TextParseUtil.shallBeIncluded(..., $VAR, ...)" + - pattern: "com.opensymphony.xwork2.util.TextParseUtil.commaDelimitedStringToSet(..., $VAR, ...)" + - pattern: "($P:com.opensymphony.xwork2.util.TextParser).evaluate(..., $VAR, ...)" + - pattern: "($P:com.opensymphony.xwork2.util.OgnlTextParser).evaluate(..., $VAR, ...)" + - pattern: "($P:com.opensymphony.xwork2.ognl.OgnlReflectionProvider).getGetMethod(..., $VAR, ...)" + - pattern: "($P:com.opensymphony.xwork2.ognl.OgnlReflectionProvider).getSetMethod(..., $VAR, ...)" + - pattern: "($P:com.opensymphony.xwork2.ognl.OgnlReflectionProvider).getField(..., $VAR, ...)" + - pattern: "($P:com.opensymphony.xwork2.ognl.OgnlReflectionProvider).setProperties(..., $VAR, ...)" + - pattern: "($P:com.opensymphony.xwork2.ognl.OgnlReflectionProvider).setProperty(...,$VAR, ...)" + - pattern: "($P:com.opensymphony.xwork2.ognl.OgnlReflectionProvider).getValue(...,$VAR, ...)" + - pattern: "($P:com.opensymphony.xwork2.ognl.OgnlReflectionProvider).setValue(...,$VAR, ...)" + - pattern: "($P:com.opensymphony.xwork2.util.reflection.ReflectionProvider).getGetMethod(..., $VAR, ...)" + - pattern: "($P:com.opensymphony.xwork2.util.reflection.ReflectionProvider).getSetMethod(..., $VAR, ...)" + - pattern: "($P:com.opensymphony.xwork2.util.reflection.ReflectionProvider).getField(..., $VAR, ...)" + - pattern: "($P:com.opensymphony.xwork2.util.reflection.ReflectionProvider).setProperties(..., $VAR, ...)" + - pattern: "($P:com.opensymphony.xwork2.util.reflection.ReflectionProvider).setProperty(..., $VAR, ...)" + - pattern: "($P:com.opensymphony.xwork2.util.reflection.ReflectionProvider).getValue(..., $VAR, ...)" + - pattern: "($P:com.opensymphony.xwork2.util.reflection.ReflectionProvider).setValue(..., $VAR, ...)" + - pattern: "($P:com.opensymphony.xwork2.ognl.OgnlUtil).setProperties(..., $VAR, ...)" + - pattern: "($P:com.opensymphony.xwork2.ognl.OgnlUtil).setProperty(..., $VAR, ...)" + - pattern: "($P:com.opensymphony.xwork2.ognl.OgnlUtil).getValue(..., $VAR, ...)" + - pattern: "($P:com.opensymphony.xwork2.ognl.OgnlUtil).setValue(..., $VAR, ...)" + - pattern: "($P:com.opensymphony.xwork2.ognl.OgnlUtil).callMethod(..., $VAR, ...)" + - pattern: "($P:com.opensymphony.xwork2.ognl.OgnlUtil).compile(..., $VAR, ...)" + - pattern: "($P:org.apache.struts2.util.VelocityStrutsUtil).evaluate(...)" + - pattern: "org.apache.struts2.util.StrutsUtil.findString(...)" + - pattern: "org.apache.struts2.util.StrutsUtil.findValue(..., $VAL)" + - pattern: "org.apache.struts2.util.StrutsUtil.getText(...)" + - pattern: "org.apache.struts2.util.StrutsUtil.translateVariables(...)" + - pattern: "org.apache.struts2.util.StrutsUtil.makeSelectList(..., $VAR, ...)" + - pattern: "($T:org.apache.struts2.views.jsp.ui.OgnlTool).findValue(..., $VAR, ...)" + - pattern: "($V:com.opensymphony.xwork2.util.ValueStack).findString(...)" + - pattern: "($V:com.opensymphony.xwork2.util.ValueStack).findValue(..., $VAR, ...)" + - pattern: "($V:com.opensymphony.xwork2.util.ValueStack).setValue(..., $VAR, ...)" + - pattern: "($V:com.opensymphony.xwork2.util.ValueStack).setParameter(..., $VAR, ...)" +- id: kotlin_inject_rule-SpotbugsPathTraversalAbsolute + languages: + - "kotlin" + message: | + The software uses an HTTP request parameter to construct a pathname that should be within a + restricted directory, but it does not properly neutralize absolute path sequences such as + "/abs/path" that can resolve to a location that is outside of that directory. See + http://cwe.mitre.org/data/definitions/36.html for more information. + severity: "WARNING" + metadata: + shortDescription: "Improper limitation of a pathname to a restricted directory ('Path Traversal')" + category: "security" + cwe: "CWE-22" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + technology: + - "kotlin" + security-severity: "MEDIUM" + + mode: "taint" + pattern-sanitizers: + - pattern: "org.apache.commons.io.FilenameUtils.getName(...)" + pattern-sinks: + - patterns: + - pattern-inside: | + $U = java.net.URI($VAR) + - pattern-either: + - pattern-inside: |- + java.io.File($U) + - pattern-inside: |- + java.nio.file.Paths.get($U) + - pattern: "$VAR" + - patterns: + - pattern-inside: |- + java.io.RandomAccessFile($INPUT,...) + - pattern: "$INPUT" + - pattern: "java.io.FileReader(...)" + - pattern: "javax.activation.FileDataSource(...)" + - pattern: "java.io.FileInputStream(...)" + - pattern: "java.io.File(...)" + - pattern: "java.nio.file.Paths.get(...)" + - pattern: "java.io.File.createTempFile(...)" + - pattern: "java.io.File.createTempDirectory(...)" + - pattern: "java.nio.file.Files.createTempFile(...)" + - pattern: "java.nio.file.Files.createTempDirectory(...)" + - patterns: + - pattern: "$SRC.$METHOD(...)" + - metavariable-pattern: + metavariable: "$SRC" + pattern-either: + - pattern: "getClass()" + - pattern: "getClass().getClassLoader()" + - pattern: "($C: ClassLoader)" + - pattern: "($C: Class)" + - pattern: "$CLZ.getClassLoader()" + - metavariable-pattern: + metavariable: "$METHOD" + pattern-either: + - pattern: "getResourceAsStream" + - pattern: "getResource" + - patterns: + - pattern-inside: |- + java.io.FileWriter($PATH, ...) + - pattern: "$PATH" + - patterns: + - pattern-inside: |- + java.io.FileOutputStream($PATH, ...) + - pattern: "$PATH" + pattern-sources: + - pattern: "($REQ: HttpServletRequest).getParameter(...)" + - patterns: + - pattern-inside: |- + fun $FUNC(..., @RequestParam $REQ:$TYPE, ...) {...} + - focus-metavariable: "$REQ" +- id: kotlin_inject_rule-SqlInjection + languages: + - "kotlin" + message: | + The input values included in SQL queries need to be passed in safely. Bind + variables in prepared statements can be used to easily mitigate the risk of + SQL injection. + options: + taint_assume_safe_functions: true + metadata: + shortDescription: "Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')" + category: "security" + cwe: "CWE-89" + technology: + - "java" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "CRITICAL" + severity: "ERROR" + + mode: taint + pattern-sources: + - patterns: + - pattern-inside: "fun $FUNC(..., $SRC: String, ...) { ... }" + - pattern: $SRC + pattern-propagators: + - pattern: $SB.append($SRC) + from: $SRC + to: $SB + - patterns: + - pattern: $F(..., $SRC, ...) + - focus-metavariable: $F + - pattern-either: + - pattern: String.format + - pattern: StringBuilder + from: $SRC + to: $F + pattern-sinks: + - patterns: + - pattern-either: + - pattern: "($PM: javax.jdo.PersistenceManager).newQuery($ARG)" + - pattern: "($PM: javax.jdo.PersistenceManager).newQuery(..., $ARG)" + - pattern: "($Q: javax.jdo.Query).setFilter($ARG)" + - pattern: "($Q: javax.jdo.Query).setGrouping($ARG)" + - pattern: "org.hibernate.criterion.Restrictions.sqlRestriction($ARG, ...)" + - pattern: "($S: org.hibernate.Session).createQuery($ARG, ...)" + - pattern: "($S: org.hibernate.Session).createSQLQuery($ARG, ...)" + - pattern: "($S: java.sql.Statement).executeQuery($ARG, ...)" + - pattern: "($S: java.sql.Statement).execute($ARG, ...)" + - pattern: "($S: java.sql.Statement).executeUpdate($ARG, ...)" + - pattern: "($S: java.sql.Statement).executeLargeUpdate($ARG, ...)" + - pattern: "($S: java.sql.Statement).addBatch($ARG, ...)" + - pattern: "($S: java.sql.PreparedStatement).executeQuery($ARG, ...)" + - pattern: "($S: java.sql.PreparedStatement).execute($ARG, ...)" + - pattern: "($S: java.sql.PreparedStatement).executeUpdate($ARG, ...)" + - pattern: "($S: java.sql.PreparedStatement).executeLargeUpdate($ARG, ...)" + - pattern: "($S: java.sql.PreparedStatement).addBatch($ARG, ...)" + - pattern: "($S: java.sql.Connection).prepareCall($ARG, ...)" + - pattern: "($S: java.sql.Connection).prepareStatement($ARG, ...)" + - pattern: "($S: java.sql.Connection).nativeSQL($ARG, ...)" + - pattern: "org.springframework.jdbc.core.PreparedStatementCreatorFactory($ARG, ...)" + - pattern: "($F: org.springframework.jdbc.core.PreparedStatementCreatorFactory).newPreparedStatementCreator($ARG, ...)" + - pattern: "($O: org.springframework.jdbc.core.JdbcOperations).batchUpdate($ARG, ...)" + - pattern: "($O: org.springframework.jdbc.core.JdbcOperations).execute($ARG, ...)" + - pattern: "($O: org.springframework.jdbc.core.JdbcOperations).query($ARG, ...)" + - pattern: "($O: org.springframework.jdbc.core.JdbcOperations).queryForList($ARG, ...)" + - pattern: "($O: org.springframework.jdbc.core.JdbcOperations).queryForMap($ARG, ...)" + - pattern: "($O: org.springframework.jdbc.core.JdbcOperations).queryForObject($ARG, ...)" + - pattern: "($O: org.springframework.jdbc.core.JdbcOperations).queryForObject($ARG, ...)" + - pattern: "($O: org.springframework.jdbc.core.JdbcOperations).queryForRowSet($ARG, ...)" + - pattern: "($O: org.springframework.jdbc.core.JdbcOperations).queryForInt($ARG, ...)" + - pattern: "($O: org.springframework.jdbc.core.JdbcOperations).queryForLong($ARG, ...)" + - pattern: "($O: org.springframework.jdbc.core.JdbcOperations).update($ARG, ...)" + - pattern: "($O: org.springframework.jdbc.core.JdbcTemplate).batchUpdate($ARG, ...)" + - pattern: "($O: org.springframework.jdbc.core.JdbcTemplate).execute($ARG, ...)" + - pattern: "($O: org.springframework.jdbc.core.JdbcTemplate).query($ARG, ...)" + - pattern: "($O: org.springframework.jdbc.core.JdbcTemplate).queryForList($ARG, ...)" + - pattern: "($O: org.springframework.jdbc.core.JdbcTemplate).queryForMap($ARG, ...)" + - pattern: "($O: org.springframework.jdbc.core.JdbcTemplate).queryForObject($ARG, ...)" + - pattern: "($O: org.springframework.jdbc.core.JdbcTemplate).queryForRowSet($ARG, ...)" + - pattern: "($O: org.springframework.jdbc.core.JdbcTemplate).queryForInt($ARG, ...)" + - pattern: "($O: org.springframework.jdbc.core.JdbcTemplate).queryForLong($ARG, ...)" + - pattern: "($O: org.springframework.jdbc.core.JdbcTemplate).update($ARG, ...)" + - pattern: "($O: io.vertx.sqlclient.SqlClient).query($ARG, ...)" + - pattern: "($O: io.vertx.sqlclient.SqlClient).preparedQuery($ARG, ...)" + - pattern: "($O: io.vertx.sqlclient.SqlConnection).prepare($ARG, ...)" + - pattern: "($O: org.apache.turbine.om.peer.BasePeer).executeQuery($ARG, ...)" + - pattern: "($O: org.apache.torque.util.BasePeer).executeQuery($ARG, ...)" + - pattern: "($O: javax.persistence.EntityManager).createQuery($ARG, ...)" + - pattern: "($O: javax.persistence.EntityManager).createNativeQuery($ARG, ...)" + - pattern: "($H: org.jdbi.v3.core.Handle).createQuery($ARG, ...)" + - pattern: "($H: org.jdbi.v3.core.Handle).createScript($ARG, ...)" + - pattern: "($H: org.jdbi.v3.core.Handle).createUpdate($ARG, ...)" + - pattern: "($H: org.jdbi.v3.core.Handle).execute($ARG, ...)" + - pattern: "($H: org.jdbi.v3.core.Handle).prepareBatch($ARG, ...)" + - pattern: "($H: org.jdbi.v3.core.Handle).select($ARG, ...)" + - pattern: "org.jdbi.v3.core.statement.Script($H, $ARG)" + - pattern: "org.jdbi.v3.core.statement.Update($H, $ARG)" + - pattern: "org.jdbi.v3.core.statement.PreparedBatch($H, $ARG)" + - focus-metavariable: $ARG +- id: kotlin_ldap_rule-AnonymousLDAP + languages: + - "kotlin" + message: | + Without proper access control, executing an LDAP statement that contains a + user-controlled value can allow an attacker to abuse poorly configured LDAP + context + metadata: + shortDescription: "Missing authentication for critical function (LDAP)" + category: "security" + cwe: "CWE-306" + owasp: + - "A2:2017-Broken Authentication" + - "A07:2021-Identification and Authentication Failures" + security-severity: "MEDIUM" + severity: "WARNING" + + patterns: + - pattern-inside: | + import javax.naming.Context + ... + - pattern: '$ENV[Context.SECURITY_AUTHENTICATION] = "none"' +- id: kotlin_password_rule-ConstantDBPassword + pattern: 'java.sql.DriverManager.getConnection($URI, $USR, "...")' + message: | + A potential hard-coded password was identified in a database connection string. + Passwords should not be stored directly in code + but loaded from secure locations such as a Key Management System (KMS). + + The purpose of using a Key Management System is so access can be audited and keys easily + rotated + in the event of a breach. By hardcoding passwords, it will be extremely difficult to determine + when or if, a key is compromised. + + The recommendation on which KMS to use depends on the environment the application is running + in: + + - For Google Cloud Platform consider [Cloud Key Management](https://cloud.google.com/kms/docs) + - For Amazon Web Services consider [AWS Key Management](https://aws.amazon.com/kms/) + - For on premise or other alternatives to cloud providers, consider [Hashicorp's + Vault](https://www.vaultproject.io/) + - For other cloud providers, please see their documentation + severity: "ERROR" + metadata: + shortDescription: "Use of hard-coded password" + category: "security" + cwe: "CWE-259" + owasp: + - "A2:2017-Broken Authentication" + - "A07:2021-Identification and Authentication Failures" + technology: + - "kotlin" + security-severity: "Critical" + languages: + - "kotlin" +- id: kotlin_password_rule-EmptyDBPassword + pattern: "java.sql.DriverManager.getConnection($URI, $USR, \"\");" + message: | + The application does not provide authentication when communicating a database + server. It is strongly recommended that the database server be configured with + authentication and restrict what queries users can execute. + + Please see your database server's documentation on how to configure a password. + + Additionally, passwords should not be stored directly in code + but loaded from secure locations such as a Key Management System (KMS). + + The purpose of using a Key Management System is so access can be audited and keys easily + rotated + in the event of a breach. By hardcoding passwords, it will be extremely difficult to determine + when or if, a key is compromised. + + The recommendation on which KMS to use depends on the environment the application is running + in: + + - For Google Cloud Platform consider [Cloud Key Management](https://cloud.google.com/kms/docs) + - For Amazon Web Services consider [AWS Key Management](https://aws.amazon.com/kms/) + - For on premise or other alternatives to cloud providers, consider [Hashicorp's + Vault](https://www.vaultproject.io/) + - For other cloud providers, please see their documentation + severity: "ERROR" + metadata: + shortDescription: "Missing authentication for critical function (database)" + category: "security" + cwe: "CWE-306" + owasp: + - "A2:2017-Broken Authentication" + - "A07:2021-Identification and Authentication Failures" + technology: + - "kotlin" + security-severity: "Critical" + languages: + - "kotlin" + +- id: kotlin_perm_rule-DangerousPermissions + languages: + - "kotlin" + message: | + Do not grant dangerous combinations of permissions. + metadata: + shortDescription: "Insecure inherited permissions" + category: "security" + cwe: "CWE-277" + owasp: + - "A5:2017-Broken Access Control" + - "A01:2021-Broken Access Control" + confidence: "HIGH" + security-severity: "MEDIUM" + severity: "WARNING" + + patterns: + - pattern-either: + - patterns: + - pattern-inside: | + $PC = $X.getPermissions(...) + ... + - pattern: $PC.add($PERMISSION) + - pattern: | + $REFVAR = $PERMISSION + ...; + ($PC: PermissionCollection).add($REFVAR) + - pattern: '($PC: PermissionCollection).add($PERMISSION)' + - metavariable-pattern: + metavariable: "$PERMISSION" + pattern-either: + - pattern: 'ReflectPermission("suppressAccessChecks")' + - pattern: 'RuntimePermission("createClassLoader")' +- id: kotlin_perm_rule-OverlyPermissiveFilePermissionInline + languages: + - "kotlin" + message: | + Overly permissive file permission + metadata: + shortDescription: "Incorrect permission assignment for critical resource" + cwe: "CWE-732" + owasp: + - "A5:2017-Broken Access Control" + - "A01:2021-Broken Access Control" + category: "security" + confidence: "HIGH" + security-severity: "MEDIUM" + severity: "WARNING" + + patterns: + - pattern-either: + - pattern: "java.nio.file.Files.setPosixFilePermissions(..., java.nio.file.attribute.PosixFilePermissions.fromString(\"$PERM_STRING\"));" + - pattern: | + $PERMISSIONS = java.nio.file.attribute.PosixFilePermissions.fromString("$PERM_STRING"); + ... + java.nio.file.Files.setPosixFilePermissions(..., $PERMISSIONS); + - metavariable-regex: + metavariable: "$PERM_STRING" + regex: "[rwx-]{6}[rwx]{1,}" +- id: kotlin_script_rule-ScriptInjection + languages: + - "kotlin" + message: | + The software constructs all or part of a code segment using externally-influenced + input from an upstream component, but it does not neutralize or incorrectly + neutralizes special elements that could modify the syntax or behavior of the + intended code segment. + severity: "ERROR" + metadata: + shortDescription: "Improper control of generation of code ('Code Injection')" + category: "security" + cwe: "CWE-94" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "CRITICAL" + + mode: "taint" + pattern-sinks: + - patterns: + - patterns: + - pattern-inside: | + $ENGINE = $F.getEngineByExtension(...) + ... + - pattern: "$ENGINE.eval($ARG, ...);" + - pattern-not: '$ENGINE.eval("...");' + - pattern-not: '$ENGINE.eval("...", ($BINDING: javax.script.Bindings));' + - patterns: + - pattern: "($ENGINE: javax.script.ScriptEngine).eval($ARG, ...);" + - pattern-not: '($ENGINE: javax.script.ScriptEngine).eval("...");' + - pattern-not: '($ENGINE: javax.script.ScriptEngine).eval("...", ($BINDING: javax.script.Bindings));' + - pattern: "($INVC: javax.script.Invocable).invokeFunction(..., $ARG)" + - pattern: "($INVC: javax.script.Invocable).invokeMethod(..., $ARG)" + pattern-sources: + - patterns: + - pattern-inside: |- + fun $FUNC(..., $VAR: String, ...) { ... } + - pattern: "$VAR" +- id: kotlin_smtp_rule-InsecureSmtp + languages: + - "kotlin" + message: | + Server identity verification is disabled when making SSL connections. + metadata: + shortDescription: "Improper validation of certificate with host mismatch" + category: "security" + cwe: "CWE-297" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + security-severity: "CRITICAL" + severity: "ERROR" + + patterns: + - pattern-either: + - pattern-inside: | + $E = org.apache.commons.mail.SimpleEmail(...) + ... + - pattern-inside: | + $E = org.apache.commons.mail.Email(...) + ... + - pattern-inside: | + $E = org.apache.commons.mail.MultiPartEmail(...) + ... + - pattern-inside: | + $E = org.apache.commons.mail.HtmlEmail(...) + ... + - pattern-inside: | + $E = org.apache.commons.mail.ImageHtmlEmail(...) + ... + - pattern-not: | + $E.setSSLOnConnect(true) + ... + $E.setSSLCheckServerIdentity(true) +- id: kotlin_smtp_rule-SmtpClient + languages: + - "kotlin" + message: | + Simple Mail Transfer Protocol (SMTP) is a the text based protocol used for + email delivery. Like with HTTP, headers are separate by new line separator. If + kuser input is place in a header line, the application should remove or replace + new line characters (CR / LF). You should use a safe wrapper such as Apache + Common Email and Simple Java Mail which filter special characters that can lead + to header injection. + metadata: + shortDescription: "Improper neutralization of special elements used in a command" + category: "security" + cwe: "CWE-77" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "CRITICAL" + severity: "ERROR" + + patterns: + - pattern-inside: | + $M = MimeMessage(...); + ... + - pattern-either: + - patterns: + - pattern-either: + - pattern: "$M.setSubject($VAR)" + - pattern: "$M.addHeader($ARG, $VAR)" + - pattern: "$M.addHeader($VAR, $ARG)" + - pattern: "$M.setDescription($VAR)" + - pattern: "$M.setDisposition($VAR)" + - metavariable-regex: + metavariable: $VAR + regex: "^[a-zA-Z_$][a-zA-Z0-9_$]*$" + - patterns: + - pattern-either: + - pattern: "$M.setSubject($OBJ.$GETTER(...))" + - pattern: "$M.setSubject($OBJ.$GETTER(...) + ...)" + - pattern: "$M.setSubject(... + $OBJ.$GETTER(...))" + - pattern: "$M.setSubject(... + $OBJ.$GETTER(...) + ...)" + - pattern: "$M.addHeader($ARG, $OBJ.$GETTER(...))" + - pattern: "$M.addHeader($ARG, $OBJ.$GETTER(...) + ...)" + - pattern: "$M.addHeader($ARG, ... + $OBJ.$GETTER(...))" + - pattern: "$M.addHeader($ARG, ... + $OBJ.$GETTER(...) + ...)" + - pattern: "$M.addHeader($OBJ.$GETTER(...), $ARG)" + - pattern: "$M.addHeader($OBJ.$GETTER(...) + ..., $ARG)" + - pattern: "$M.addHeader(... + $OBJ.$GETTER(...), $ARG)" + - pattern: "$M.addHeader(... + $OBJ.$GETTER(...) + ..., $ARG)" + - pattern: "$M.setDescription($OBJ.$GETTER(...))" + - pattern: "$M.setDisposition($OBJ.$GETTER(...) + ...)" + - pattern: "$M.setDisposition(... + $OBJ.$GETTER(...))" + - pattern: "$M.setDisposition(... + $OBJ.$GETTER(...) + ...)" + - metavariable-regex: + metavariable: $GETTER + regex: ^get +- id: kotlin_ssrf_rule-SSRF + languages: + - "kotlin" + message: | + Server-Side Request Forgery occur when a web server executes a request to a user supplied + destination parameter that is not validated. Such vulnerabilities could allow an attacker to + access internal services or to launch attacks from your web server. + metadata: + shortDescription: "Server-Side Request Forgery (SSRF)" + category: "security" + cwe: "CWE-918" + owasp: + - "A1:2017-Injection" + - "A10:2021-Server-Side Request Forgery" + security-severity: "CRITICAL" + severity: "ERROR" + + pattern-either: + - patterns: + - pattern-either: + - pattern-inside: | + import java.net.*; + ... + - pattern-inside: | + import java.net.URL; + ... + - pattern-inside: | + import java.net.URI; + ... + - pattern: "$TYPE(...). ... .$FUNC" + - pattern-not: '$TYPE("..."). ... .$FUNC' + - metavariable-pattern: + metavariable: "$FUNC" + pattern-either: + - pattern: "connect" + - pattern: "GetContent" + - pattern: "openConnection" + - pattern: "openStream" + - pattern: "getContent" + - pattern: "content" + - metavariable-pattern: + metavariable: "$TYPE" + pattern-either: + - pattern: "URL" + - pattern: "java.net.URL" + - pattern: "URI" + - pattern: "java.net.URI" + - patterns: + - pattern-either: + - pattern-inside: | + import java.net.*; + ... + - pattern-inside: | + import java.net.InetSocketAddress; + ... + - pattern: | + InetSocketAddress(..., $PORT) + - pattern-not: | + InetSocketAddress("...", $PORT) +- id: kotlin_strings_rule-BadHexConversion + languages: + - "kotlin" + message: | + When converting a byte array containing a hash signature to a human readable string, a + conversion mistake can be made if the array is read byte by byte. + metadata: + shortDescription: "Incorrect type conversion or cast" + cwe: "CWE-704" + category: "security" + confidence: "HIGH" + owasp: + - "A6:2017-Security Misconfiguration" + - "A05:2021-Security Misconfiguration" + security-severity: "MEDIUM" + severity: "WARNING" + + patterns: + - pattern-inside: | + $B_ARR = ($MD: java.security.MessageDigest).digest(...); + ... + - pattern-either: + - pattern: | + for($B in $B_ARR) { + ... + $B_TOSTR + } + - pattern: | + while(...) { + ... + $B_TOSTR + } + - pattern: | + do { + ... + $B_TOSTR + } while(...) + - metavariable-pattern: + metavariable: $B_TOSTR + patterns: + - pattern-either: + - pattern: java.lang.Integer.toHexString($B_TOINT) + - pattern: Integer.toHexString($B_TOINT) + - pattern: $B_TOINT.toHexString(...) + - metavariable-pattern: + metavariable: $B_TOINT + pattern-either: + - pattern: $B_ARR[...].toInt() + - pattern: $B_ARR[...] + - pattern: $B.toInt() + - pattern: $B +- id: kotlin_strings_rule-FormatStringManipulation + languages: + - "kotlin" + message: | + Allowing user input to control format parameters could enable an attacker to cause exceptions + to be thrown or leak information.Attackers may be able to modify the format string argument, + such that an exception is thrown. If this exception is left uncaught, it may crash the + application. Alternatively, if sensitive information is used within the unused arguments, + attackers may change the format string to reveal this information. + metadata: + shortDescription: "Use of externally-controlled format string" + cwe: "CWE-134" + category: "security" + confidence: "HIGH" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "CRITICAL" + severity: "ERROR" + + patterns: + - pattern-either: + - patterns: + - pattern-inside: | + $INPUT = ($REQ: HttpServletRequest).getParameter(...) + ... + - pattern-inside: | + $FORMAT_STR = ... + $INPUT + ... + - patterns: + - pattern-inside: | + $INPUT = ($REQ: HttpServletRequest).getParameter(...) + ... + - pattern-inside: | + $FORMAT_STR = ... + $INPUT + ... + ... + - pattern-inside: | + $FORMAT_STR = ... + ($REQ: HttpServletRequest).getParameter(...) + ... + ... + - pattern-inside: | + $FORMAT_STR = ... + ($REQ: HttpServletRequest).getParameter(...) + ... + - pattern-either: + - pattern: "String.format($FORMAT_STR, ...)" + - pattern: "String.format(java.util.Locale.$LOCALE, $FORMAT_STR, ...)" + - patterns: + - pattern-inside: | + $F = java.util.Formatter(...) + ... + - pattern-either: + - pattern: "$F.format($FORMAT_STR, ...)" + - pattern: "$F.format(java.util.Locale.$LOCALE, $FORMAT_STR, ...)" + - pattern: "($F: java.io.PrintStream).printf($FORMAT_STR, ...)" + - pattern: "($F: java.io.PrintStream).printf(java.util.Locale.$LOCALE, $FORMAT_STR, ...)" + - pattern: "($F: java.io.PrintStream).format($FORMAT_STR, ...)" + - pattern: "($F: java.io.PrintStream).format(java.util.Locale.$LOCALE, $FORMAT_STR, ...)" + - pattern: "System.out.printf($FORMAT_STR, ...)" + - pattern: "System.out.printf(java.util.Locale.$LOCALE, $FORMAT_STR, ...)" + - pattern: "System.out.format($FORMAT_STR, ...)" + - pattern: "System.out.format(java.util.Locale.$LOCALE, $FORMAT_STR, ...)" +- id: kotlin_strings_rule-ModifyAfterValidation + languages: + - "kotlin" + message: | + CERT: IDS11-J. Perform any string modifications before validation + metadata: + shortDescription: "Collapse of data into unsafe value" + category: "security" + cwe: "CWE-182" + confidence: "HIGH" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "MEDIUM" + severity: "WARNING" + + patterns: + - pattern-inside: | + $PATTERN = Pattern.compile(...) + ... + - pattern-inside: | + $PATTERN.matcher($VAR) + ... + - pattern-either: + - pattern: | + $VAR + $OTHER + - patterns: + - pattern: | + $VAR.$METHOD(...) + - metavariable-regex: + metavariable: "$METHOD" + regex: "(replace|replaceAll|replaceFirst|concat)" +- id: kotlin_strings_rule-NormalizeAfterValidation + languages: + - "kotlin" + message: | + IDS01-J. Normalize strings before validating them + metadata: + shortDescription: "Incorrect behavior order: validate before canonicalize" + category: "security" + cwe: "CWE-180" + confidence: "HIGH" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "MEDIUM" + severity: "WARNING" + + patterns: + - pattern: | + $Y = java.util.regex.Pattern.compile("[<>]"); + ... + $Y.matcher($VAR); + ... + java.text.Normalizer.normalize($VAR, ...); +- id: kotlin_templateinjection_rule-TemplateInjection + languages: + - "kotlin" + message: | + A malicious user in control of a template can run malicious code on the + server-side. Velocity templates should be seen as scripts. + metadata: + shortDescription: "Improper control of generation of code ('Code Injection')" + category: "security" + cwe: "CWE-94" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "CRITICAL" + severity: "ERROR" + + pattern-either: + - patterns: + - pattern: "org.apache.velocity.app.Velocity.evaluate(..., $VAR)" + - pattern-not: 'org.apache.velocity.app.Velocity.evaluate(..., "...")' + - patterns: + - pattern-not-inside: | + $C = ($CFG: freemarker.template.Configuration).getTemplate("..."); + ... + - pattern-inside: | + $C = ($CFG: freemarker.template.Configuration).getTemplate($IN); + ... + - pattern: "$C.process(...)" + - patterns: + - pattern-inside: | + import com.mitchellbosecke.pebble.PebbleEngine; + ... + - pattern-inside: | + $C = $T.getTemplate($IN); + ... + - pattern-not-inside: | + $C = $T.getTemplate("..."); + ... + - pattern: "$C.evaluate(...)" +- id: kotlin_unsafe_rule-ExternalConfigControl + languages: + - "kotlin" + message: | + Allowing external control of system settings can disrupt service or cause an application to + behave in unexpected, and potentially malicious ways. An attacker could cause an error by + providing a nonexistent catalog name or connect to an unauthorized portion of the database. + severity: "WARNING" + metadata: + shortDescription: "External control of system or configuration setting" + category: "security" + cwe: "CWE-15" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + technology: + - "kotlin" + security-severity: "MEDIUM" + + patterns: + - metavariable-pattern: + metavariable: "$GET_PARAMETER" + pattern-either: + - pattern: '($REQ: HttpServletRequest).getParameter' + - pattern: '($REQ: HttpServletRequest?)?.getParameter' + - metavariable-pattern: + metavariable: "$SET_CATALOG" + pattern-either: + - pattern: '($CONN: java.sql.Connection).setCatalog' + - pattern: '($CONN: java.sql.Connection?)?.setCatalog' + - pattern: |- + $TAINTED = $GET_PARAMETER(...) + ... + $SET_CATALOG($TAINTED) +- id: rules_lgpl_kotlin_other_rule-android-kotlin-webview-debug + patterns: + - pattern: | + $X.setWebContentsDebuggingEnabled(true) + - pattern-inside: | + WebView + ... + message: | + Remote WebView debugging is enabled.This can introduce security + risks as it allows remote debugging tools, such as Chrome DevTools, + to inspect and manipulate the WebView content. This can potentially + expose sensitive information, including user data, session tokens, + and other confidential data, to unauthorized parties. + + To fix this security issue, you should disable remote WebView + debugging in production builds of your app. Here's how you can do it: + ``` + import WebKit + + class ViewController: UIViewController { + + override func viewDidLoad() { + super.viewDidLoad() + + // Disable remote WebView debugging in production builds + #if DEBUG + WebViewConfiguration.shared().preferences.setValue(true, forKey: "developerExtrasEnabled") + #else + WebViewConfiguration.shared().preferences.setValue(false, forKey: "developerExtrasEnabled") + #endif + + // Other setup code... + } + + // Other methods... + } + ``` + + languages: + - kotlin + severity: WARNING + metadata: + category: security + cwe: "CWE-489" + shortDescription: "Leftover debug code" + owasp: + - "A6:2017-Security Misconfiguration" + - "A05:2021-Security Misconfiguration" + security-severity: MEDIUM +- id: kotlin_xml_rule-SAMLIgnoreComments + languages: + - "kotlin" + message: | + Ignoring XML comments in SAML may lead to authentication bypass + metadata: + shortDescription: "Weak authentication" + cwe: "CWE-1390" + category: "security" + owasp: + - "A5:2017-Broken Access Control" + - "A01:2021-Broken Access Control" + security-severity: "MEDIUM" + severity: "WARNING" + + pattern: "($POOL: org.opensaml.xml.parse.BasicParserPool).setIgnoreComments(false);" +- id: kotlin_xml_rule-XmlDecoder + languages: + - "kotlin" + message: | + Avoid using XMLDecoder to parse content from an untrusted source. + metadata: + shortDescription: "Deserialization of untrusted data" + category: "security" + cwe: "CWE-502" + owasp: + - "A8:2017-Insecure Deserialization" + - "A08:2021-Software and Data Integrity Failures" + security-severity: "MEDIUM" + severity: "WARNING" + + patterns: + - pattern-either: + - pattern: "($D: java.beans.XMLDecoder).readObject()" + - patterns: + - pattern: "$D.readObject()" + - pattern-inside: | + $D = XMLDecoder(...) + ... + - pattern-not: + pattern-either: + - patterns: + - pattern-inside: | + $DEC = java.beans.XMLDecoder(..., $CL) + ... + - pattern: $DEC.readObject() + - metavariable-pattern: + metavariable: $CL + patterns: + - pattern: | + object : ClassLoader() { + ... + fun loadClass(name: String, resolve: Boolean): $RET { + if($X){ + throw ... + } + ... + } + ... + } + - metavariable-pattern: + metavariable: $X + pattern-either: + - pattern: | + name != ... + - pattern: | + !$LIST.contains(name) + - patterns: + - pattern-inside: | + $CLASS_LOADER = $CL + ... + - pattern-inside: | + $DEC = java.beans.XMLDecoder(..., $CLASS_LOADER) + ... + - pattern: $DEC.readObject() + - metavariable-pattern: + metavariable: $CL + patterns: + - pattern: | + object : ClassLoader(){ + ... + fun loadClass(name: String, resolve: Boolean): $RET{ + if($X){ + throw ... + } + ... + } + ... + } + - metavariable-pattern: + metavariable: $X + pattern-either: + - pattern: | + name != ... + - pattern: | + !$LIST.contains(name) +- id: kotlin_xml_rule-XsltTransform + languages: + - "kotlin" + message: | + It is possible to attach malicious behavior to those style sheets. Therefore, if an attacker + can control the content or the source of the style sheet, he might be able to trigger remote + code execution. + metadata: + shortDescription: "XML injection (aka Blind XPath injection)" + category: "security" + cwe: "CWE-91" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "MEDIUM" + severity: "WARNING" + + mode: "taint" + pattern-sources: + - patterns: + - pattern-either: + - patterns: + - pattern-inside: | + fun $FUNC(...,$VAR: String, ...) { + ... + } + - pattern-either: + - pattern: "FileInputStream(<... $VAR ...>);" + - pattern: "javaClass.getResourceAsStream(<... $VAR ...>)" + - patterns: + - pattern-inside: | + class $CLZ { + var $X = "..."; + ... + } + - pattern-inside: | + fun $FUNC(...,$Y: String, ...) { + ... + } + - pattern-either: + - pattern: "FileInputStream($X + $Y);" + - pattern: "javaClass.getResourceAsStream($X + $Y)" + pattern-sinks: + - patterns: + - pattern-either: + - pattern-inside: |- + ($T: javax.xml.transform.TransformerFactory).newTransformer($SRC, ...) + - pattern-inside: |- + ($T: javax.xml.transform.Transformer).transform($SRC, ...) + # flow instead of type assertion + - patterns: + - pattern-inside: |- + $FACTORY = javax.xml.transform.TransformerFactory.newInstance(...) + ... + - pattern-inside: $FACTORY.newTransformer($SRC, ...) + - patterns: + - pattern-inside: |- + $FACTORY = javax.xml.transform.TransformerFactory(...) + ... + - pattern-inside: |- + $T = $FACTORY.newTransformer(...) + ... + - pattern-inside: |- + $T.transform($SRC, ...) + - pattern: "$SRC" +- id: kotlin_xpathi_rule-XpathInjection + languages: + - "kotlin" + message: | + The input values included in SQL queries need to be passed in safely. Bind + variables in prepared statements can be used to easily mitigate the risk of + SQL injection. + metadata: + shortDescription: "Improper neutralization of data within XPath expressions ('XPath Injection')" + category: "security" + cwe: "CWE-643" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "CRITICAL" + severity: "ERROR" + + mode: "taint" + pattern-sources: + - patterns: + - pattern-inside: | + fun $FUNC(..., $VAR: $T, ...) { + ... + } + - pattern: "$VAR" + pattern-sinks: + - patterns: + - pattern-either: + - pattern-inside: "import javax.xml.xpath.*; \n...\n" + - pattern-inside: "import javax.xml.xpath.XPath; \n...\n" + - patterns: + - pattern-either: + - patterns: + - pattern: "$X.compile($VAR)" + - pattern-not: '$X.compile("...")' + - patterns: + - pattern: "$X.evaluate($VAR, ...)" + - pattern-not: '$X.evaluate("...", ...)' + pattern-sanitizers: + - pattern-either: + - pattern-inside: | + $X.xPathVariableResolver = ...; + ...; + $X.compile("..."); + - pattern-inside: | + $X.setXPathVariableResolver(...); + ...; + $X.compile("..."); +- id: kotlin_xss_rule-WicketXSS + languages: + - "kotlin" + message: | + Disabling HTML escaping put the application at risk for Cross-Site Scripting (XSS). + metadata: + shortDescription: "Improper neutralization of input during web page generation ('Cross-site Scripting')" + category: "security" + cwe: "CWE-79" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "MEDIUM" + severity: "WARNING" + + patterns: + - pattern-inside: | + import org.apache.wicket.$A + ... + - pattern: | + $OBJ.setEscapeModelStrings(false); +- id: kotlin_xss_rule-XSSReqParamToServletWriter + languages: + - "kotlin" + message: | + Servlet reflected cross site scripting vulnerability + severity: "WARNING" + metadata: + shortDescription: "Improper neutralization of input during web page generation ('Cross-site Scripting')" + category: "security" + cwe: "CWE-79" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + technology: + - "kotlin" + security-severity: "MEDIUM" + + mode: "taint" + pattern-sanitizers: + - patterns: + - pattern-inside: |- + org.owasp.encoder.Encode.forHtml($TAINTED); + - pattern: "$TAINTED" + pattern-sinks: + - patterns: + - pattern-inside: |- + fun $FUNC(..., $RES: HttpServletResponse , ...) {...} + - pattern-inside: | + $WRITER = $RES.getWriter(); + ... + - pattern: "$WRITER.write($DATA,...);" + - pattern: "$DATA" + - patterns: + - pattern-inside: |- + fun $FUNC(..., $RES: HttpServletResponse , ...) {...} + - pattern: "$RES.getWriter().write($DATA,...);" + - pattern: "$DATA" + pattern-sources: + - patterns: + - pattern-inside: |- + fun $FUNC(..., $REQ: HttpServletRequest , ...) {...} + - pattern: "$REQ.getParameter(...);" +- id: kotlin_xxe_rule-SaxParserXXE + languages: + - "kotlin" + message: | + XML External Entity (XXE) attacks can occur when an XML parser supports XML + entities while processing XML received from an untrusted source. + metadata: + shortDescription: "Improper restriction of XML external entity reference ('XXE')" + category: "security" + cwe: "CWE-611" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "CRITICAL" + severity: "ERROR" + + patterns: + - pattern-inside: | + $SF = SAXParserFactory.newInstance() + ... + - pattern-not-inside: | + $SF.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + ... + - pattern-not-inside: | + $SF.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + ... + - pattern-inside: | + $P = $SFP.newSAXParser(); + ... + - pattern: "$P.parse(...);" +- id: kotlin_xxe_rule-XMLRdr + languages: + - "kotlin" + message: | + XML External Entity (XXE) attacks can occur when an XML parser supports XML + entities while processing XML received from an untrusted source. + metadata: + shortDescription: "Improper restriction of XML external entity reference ('XXE')" + category: "security" + cwe: "CWE-611" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "CRITICAL" + severity: "ERROR" + + patterns: + - pattern-inside: | + $R = XMLReaderFactory.createXMLReader() + ... + - pattern-not-inside: | + $R.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true) + ... + - pattern: "$R.parse(...)" +- id: kotlin_xxe_rule-XMLStreamRdr + languages: + - "kotlin" + message: | + XML External Entity (XXE) attacks can occur when an XML parser supports XML + entities while processing XML received from an untrusted source. + metadata: + shortDescription: "Improper restriction of XML external entity reference ('XXE')" + category: "security" + cwe: "CWE-611" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + security-severity: "CRITICAL" + severity: "ERROR" + + patterns: + - pattern-inside: | + $SF = XMLInputFactory.newFactory(); + ... + - pattern-not-inside: | + $SF.setProperty(XMLInputFactory.SUPPORT_DTD, false); + ... + - pattern-not-inside: | + $SF.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, false); + ... + - pattern-not-inside: | + $SF.setProperty(XMLInputFactory.SUPPORT_DTD, Boolean.FALSE); + ... + - pattern-not-inside: | + $SF.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, Boolean.FALSE); + ... + - pattern: "$SF.createXMLStreamReader(...)" +- id: rules_lgpl_swift_other_rule-ios-biometric-acl + patterns: + - pattern-either: + - pattern: .biometryAny + - pattern: .userPresence + - pattern: .touchIDAny + - pattern: SecAccessControlCreateWithFlags(...) + message: | + Weak biometric ACL flag is associated with a key stored in Keychain. + With '.biometryAny/.userPresence/.touchIDAny' flag, an attacker with + the ability to add a biometry to the device can authenticate as the + user. It is recommended to use more specific and secure authentication + mechanisms like '.biometryCurrentSet' and '.touchIDCurrentSet'. + + Here's an example of how to fix the problem by using .biometryCurrentSet + for biometric authentication in Swift: + ``` + import LocalAuthentication + + // Create an instance of LAContext for biometric authentication + let context = LAContext() + + // Check if biometric authentication is available + if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: nil) { + // Use biometryCurrentSet for biometric authentication + context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, + localizedReason: "Authenticate with biometrics", + reply: { success, error in + if success { + print("Biometric authentication successful.") + // Proceed with authenticated actions + } else { + print("Biometric authentication failed: + \(error?.localizedDescription ?? "Unknown error")") + // Handle authentication failure + } + }) + } else { + print("Biometric authentication not available.") + // Fallback to alternative authentication method + } + + ``` + languages: + - swift + severity: ERROR + metadata: + category: security + cwe: "CWE-305" + shortDescription: "Authentication bypass by primary weakness" + owasp: + - "A2:2017-Broken Authentication" + - "A07:2021-Identification and Authentication Failures" + security-severity: CRITICAL +- id: rules_lgpl_swift_other_rule-ios-dtls1-used + patterns: + - pattern: + $Y.TLSMinimumSupportedProtocolVersion + - pattern-inside: | + ... + $X = "tls_protocol_version_t.DTLSv10" + ... + message: | + DTLS 1.2 should be used. Detected old version - DTLS 1.0. + DTLS (Datagram Transport Layer Security) 1.0 suffers from + various security vulnerabilities and weaknesses, as it is + an outdated and less secure protocol compared to newer + versions such as DTLS 1.2 or 1.3. + + Here's an example of how to use DTLS 1.2: + ``` + import Network + + // Create a NWConnection instance with DTLS 1.2 + let connection = NWConnection(host: NWEndpoint.Host("example.com"), port: NWEndpoint.Port("443"), using: .dtls) + + // Start the connection + connection.start(queue: .main) + + // Handle connection state changes + connection.stateUpdateHandler = { newState in + switch newState { + case .ready: + print("Connection ready.") + // Perform data transfer or other operations + case .failed(let error): + print("Connection failed with error: \(error)") + default: + break + } + } + ``` + + languages: + - swift + severity: WARNING + metadata: + category: security + cwe: "CWE-757" + shortDescription: "Selection of less-secure algorithm during negotiation ('algorithm downgrade')" + owasp: + - "A6:2017-Security Misconfiguration" + - "A05:2021-Security Misconfiguration" + security-severity: MEDIUM +- id: rules_lgpl_swift_other_rule-ios-file-no-special + pattern-either: + - pattern: .noFileProtection + - pattern: FileProtectionType.none + message: | + The file has no special protections associated with it. + Using .noFileProtection or FileProtectionType.none for + file protection means that the file is not encrypted on disk, + leaving it vulnerable to unauthorized access if the device is + compromised or if the file is accessed outside of the app's + sandbox. To enhance security, it's crucial to use appropriate + file protection attributes based on the sensitivity of the data + being stored. For sensitive data, you should use file protection + options that encrypt the data on disk, such as + FileProtectionType.complete or + FileProtectionType.completeUnlessOpen. + + Here's an example of how to fix the problem: + ``` + import Foundation + // Define the file URL + let fileURL = URL(fileURLWithPath: "path/to/file") + // Define data to be written to the file + let data = "Sensitive data".data(using: .utf8)! + // Write data to the file with complete file protection + do { + try data.write(to: fileURL, options: .completeFileProtection) + print("Data written to file with complete file protection.") + } catch { + print("Error writing data to file: \(error)") + } + ``` + languages: + - swift + severity: ERROR + metadata: + category: security + cwe: "CWE-312" + shortDescription: "Cleartext storage of sensitive information" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + security-severity: CRITICAL +- id: rules_lgpl_swift_other_rule-ios-keychain-weak-accessibility-value + pattern-either: + - pattern: kSecAttrAccessibleAlways + - pattern: kSecAttrAccessibleAfterFirstUnlock + message: | + A key stored in the Keychain is using a weak accessibility value. + + kSecAttrAccessibleAlways allows access to the keychain item at all + times, even when the device is locked. Storing sensitive data with + this accessibility option means that the data is accessible to anyone + who gains physical access to the device, regardless of whether it's + locked or not. This increases the risk of unauthorized access to + sensitive information. kSecAttrAccessibleAfterFirstUnlock allows access + to the keychain item only after the device has been unlocked once after + a reboot. While this provides some level of protection, the data becomes + accessible as soon as the device is unlocked for the first time after a + reboot. If sensitive data is stored with this accessibility option, it + could still be accessed by an attacker who gains physical access to the + device before it's unlocked for the first time after a reboot. + + To mitigate these security risks, it's important to use the appropriate + accessibility option based on the sensitivity of the data being stored. + For sensitive data that should only be accessible when the device is + unlocked, the kSecAttrAccessibleWhenUnlocked or + kSecAttrAccessibleWhenUnlockedThisDeviceOnly + options should be used. + + Here's an example code that fixes the problem by using the + kSecAttrAccessibleWhenUnlocked option: + ``` + import Foundation + import Security + + // Define the data to be stored in the keychain + let secretData = "superSecretData".data(using: .utf8)! + + // Create query dictionary to specify the keychain item + let query: [String: Any] = [ + kSecClass as String: kSecClassGenericPassword, + kSecAttrService as String: "com.example.myApp", + kSecAttrAccount as String: "userPassword", + kSecValueData as String: secretData, + kSecAttrAccessible as String: kSecAttrAccessibleWhenUnlocked + ] + + // Add the keychain item + let status = SecItemAdd(query as CFDictionary, nil) + if status == errSecSuccess { + print("Secret data successfully stored in keychain.") + } else { + print("Error storing secret data in keychain: \(status)") + } + ``` + languages: + - swift + severity: WARNING + metadata: + category: security + cwe: "CWE-305" + shortDescription: "Authentication bypass by primary weakness" + owasp: + - "A2:2017-Broken Authentication" + - "A07:2021-Identification and Authentication Failures" + security-severity: MEDIUM +- id: rules_lgpl_swift_other_rule-ios-tls3-not-used + pattern-either: + - patterns: + - pattern: $X.TLSMinimumSupportedProtocolVersion = $VAL + - metavariable-pattern: + metavariable: $VAL + pattern-either: + - pattern: | + .TLSv1_0 + - pattern: | + .TLSv1_1 + - pattern: | + .TLSv1_2 + message: | + The app uses TLS 1.0, TLS 1.1 or TLS 1.2. TLS 1.3 should be used instead. + TLS versions 1.1 and 1.0 were deprecated by the IETF in June 2018 due to + a number of attacks against the vulnerable versions. Use of a deprecated + TLS version may result in the unauthorized retrieval of sensitive + information. It is strongly recommended that all TLS connections + use TLS 1.3 + + TLS 1.3 includes several security improvements over previous versions, such + as stronger cryptographic algorithms and negotiation mechanisms, reducing + the risk of security vulnerabilities and attacks like BEAST and POODLE. + + + Example using TLS 1.3: + ``` + import Foundation + // Create a URLSession configuration with TLS 1.3 support + let configuration = URLSessionConfiguration.default + configuration.tlsMinimumSupportedProtocol = .TLSv13 + // Create a URLSession with the custom configuration + let session = URLSession(configuration: configuration) + // Define the URL to connect to + let url = URL(string: "https://example.com")! + // Create a data task to fetch data from the URL + let task = session.dataTask(with: url) { data, response, error in + // Handle response + if let error = error { + print("Error: \(error)") + return + } + if let httpResponse = response as? HTTPURLResponse { + print("Status code: \(httpResponse.statusCode)") + } + if let data = data { + // Process received data + print("Received data: \(data)") + } + } + // Start the data task + task.resume() + ``` + languages: + - swift + severity: ERROR + metadata: + category: security + cwe: "CWE-757" + shortDescription: "Selection of less-secure algorithm during negotiation ('algorithm downgrade')" + owasp: + - "A6:2017-Security Misconfiguration" + - "A05:2021-Security Misconfiguration" + security-severity: CRITICAL +- id: scala_cookie_rule-CookieHTTPOnly + languages: + - "scala" + message: | + A new cookie is created without the HttpOnly flag set. The HttpOnly flag is a directive to the + browser to make sure that the cookie can not be red by malicious script. When a user is the + target of a "Cross-Site Scripting", the attacker would benefit greatly from getting the session + id for example. + metadata: + category: "security" + cwe: "CWE-1004" + shortDescription: "Sensitive Cookie Without 'HttpOnly' Flag" + technology: + - "scala" + security-severity: "Low" + pattern-either: + - patterns: + - pattern: | + val $C = new javax.servlet.http.Cookie(..., ...); + ... + $RESP.addCookie($C); + - pattern-not-inside: | + val $C = new javax.servlet.http.Cookie(..., ...); + ... + $C.setHttpOnly(true); + ... + $RESP.addCookie($C); + - pattern: "(javax.servlet.http.Cookie $C).setHttpOnly(false);" + severity: "WARNING" +- id: scala_cookie_rule-CookieInsecure + languages: + - "scala" + message: | + "A new cookie is created without the Secure flag set. The Secure flag is a + directive to the browser to make sure that the cookie is not sent for insecure communication + (http://)" + metadata: + category: "security" + cwe: "CWE-539" + shortDescription: "Information Exposure Through Persistent Cookies" + technology: + - "scala" + security-severity: "Low" + patterns: + - pattern-not-inside: | + val $C = new javax.servlet.http.Cookie(..., ...); + ... + $C.setSecure(true); + ... + $RESP.addCookie($C); + - pattern-either: + - pattern: | + val $C = new javax.servlet.http.Cookie(..., ...); + ... + $RESP.addCookie($C); + - pattern: "($C:javax.servlet.http.Cookie).setSecure(false);" + severity: "WARNING" +- id: scala_cookie_rule-CookiePersistent + languages: + - "scala" + message: | + "Storing sensitive data in a persistent cookie for an extended period can lead to a breach of + confidentiality or account compromise." + metadata: + category: "security" + cwe: "CWE-614" + shortDescription: "Sensitive Cookie in HTTPS Session Without 'Secure' Attribute" + technology: + - "scala" + security-severity: "Info" + patterns: + - pattern: | + ($C: Cookie).setMaxAge($AGE) + - metavariable-comparison: + comparison: "$AGE >= 31536000" + metavariable: "$AGE" + severity: "WARNING" +- id: scala_cookie_rule-CookieUsage + languages: + - "scala" + message: | + The information stored in a custom cookie should not be sensitive or related to the session. + In most cases, sensitive data should only be stored in session and referenced by the user's + session cookie. + metadata: + category: "security" + cwe: "CWE-614" + shortDescription: "Sensitive Cookie in HTTPS Session Without 'Secure' Attribute" + technology: + - "scala" + security-severity: "Info" + patterns: + - pattern-inside: | + def $FUNC(..., $REQ: HttpServletRequest, ...): $TYPE = { + ... + } + - pattern-either: + - patterns: + - pattern-inside: | + for ($C <- $REQ.getCookies) { + ... + } + - pattern-either: + - pattern: "$C.getName" + - pattern: "$C.getValue" + - pattern: "$C.getPath" + - pattern: "($C: Cookie).getName()" + - pattern: "($C: Cookie).getValue" + - pattern: "($C: Cookie).getPath" + severity: "WARNING" +- id: scala_cookie_rule-HttpResponseSplitting + languages: + - "scala" + message: | + When an HTTP request contains unexpected CR and LF characters, the server may respond with an + output stream that is interpreted as two different HTTP responses (instead of one). An attacker + can control the second response and mount attacks such as cross-site scripting and cache + poisoning attacks. + metadata: + category: "security" + cwe: "CWE-113" + shortDescription: "Improper Neutralization of CRLF Sequences in HTTP Headers ('HTTP + Response Splitting')" + technology: + - "scala" + security-severity: "High" + mode: "taint" + pattern-sanitizers: + - patterns: + - pattern-inside: |- + $STR.replaceAll("$REPLACE_CHAR", "$REPLACE"); + - pattern: "$STR" + - metavariable-regex: + metavariable: "$REPLACE_CHAR" + regex: "(.*\\\\r\\\\n.*)" + - metavariable-regex: + metavariable: "$REPLACE" + regex: "(?!(\\\\r\\\\n))" + - pattern: "org.owasp.encoder.Encode.forUriComponent(...)" + - pattern: "org.owasp.encoder.Encode.forUri(...)" + - pattern: "java.net.URLEncoder.encode(..., $CHARSET)" + pattern-sinks: + - pattern: "new javax.servlet.http.Cookie(\"$KEY\", ...)" + - pattern: "($C:javax.servlet.http.Cookie).setValue(...)" + pattern-sources: + - pattern: "($REQ: javax.servlet.http.HttpServletRequest).getParameter(...)" + severity: "WARNING" +- id: scala_cookie_rule-RequestParamToCookie + languages: + - "scala" + message: | + This code constructs an HTTP Cookie using an untrusted HTTP parameter. If this cookie is added + to an HTTP response, it will allow a HTTP response splitting vulnerability. See + http://en.wikipedia.org/wiki/HTTP_response_splitting for more information. + metadata: + category: "security" + cwe: "CWE-113" + shortDescription: "Improper Neutralization of CRLF Sequences in HTTP Headers ('HTTP + Response Splitting')" + technology: + - "scala" + security-severity: "Info" + mode: "taint" + pattern-sanitizers: + - patterns: + - pattern-inside: |- + $STR.replaceAll("$REPLACE_CHAR", "$REPLACE"); + - pattern: "$STR" + - metavariable-regex: + metavariable: "$REPLACE_CHAR" + regex: "(.*\\\\r\\\\n.*)" + - metavariable-regex: + metavariable: "$REPLACE" + regex: "(?!(\\\\r\\\\n))" + - pattern: "org.owasp.encoder.Encode.forUriComponent(...)" + - pattern: "org.owasp.encoder.Encode.forUri(...)" + - pattern: "java.net.URLEncoder.encode(..., $CHARSET)" + pattern-sinks: + - pattern: "new javax.servlet.http.Cookie(\"$KEY\", ...);" + - patterns: + - pattern-inside: | + $C = new javax.servlet.http.Cookie("$KEY", ...); + ... + - pattern: "$C.setValue(...);" + pattern-sources: + - pattern: "($REQ: HttpServletRequest).getParameter(...);" + severity: "ERROR" +- id: scala_cookie_rule-RequestParamToHeader + languages: + - "scala" + message: | + This code directly writes an HTTP parameter to an HTTP header, which allows for a HTTP + response splitting vulnerability. See http://en.wikipedia.org/wiki/HTTP_response_splitting for + more information. + metadata: + category: "security" + cwe: "CWE-113" + shortDescription: "Improper Neutralization of CRLF Sequences in HTTP Headers ('HTTP + Response Splitting')" + technology: + - "scala" + security-severity: "High" + mode: "taint" + pattern-sanitizers: + - patterns: + - pattern-inside: |- + $STR.replaceAll("$REPLACE_CHAR", "$REPLACE"); + - pattern: "$STR" + - metavariable-regex: + metavariable: "$REPLACE_CHAR" + regex: "(.*\\\\r\\\\n.*)" + - metavariable-regex: + metavariable: "$REPLACE" + regex: "(?!(\\\\r\\\\n))" + - pattern: "org.owasp.encoder.Encode.forUriComponent(...)" + - pattern: "org.owasp.encoder.Encode.forUri(...)" + - pattern: "java.net.URLEncoder.encode(..., $CHARSET)" + pattern-sinks: + - pattern: "($RES: HttpServletResponse).setHeader(\"$KEY\", ...);" + - pattern: "($RES: HttpServletResponse).addHeader(\"$KEY\", ...);" + - pattern: "($WRP: HttpServletResponseWrapper).setHeader(\"$KEY\", ...);" + - pattern: "($WRP: HttpServletResponseWrapper).addHeader(\"$KEY\", ...);" + pattern-sources: + - pattern: "($REQ: HttpServletRequest).getParameter(...);" + severity: "ERROR" +- id: scala_cookie_rule-TrustBoundaryViolation + languages: + - "scala" + message: | + A trust boundary can be thought of as line drawn through a program. On one side + of the line, data is untrusted. On the other side of the line, data is assumed + to be trustworthy. The purpose of validation logic is to allow data to safely + cross the trust boundary - to move from untrusted to trusted. A trust boundary + violation occurs when a program blurs the line between what is trusted and what + is untrusted. By combining trusted and untrusted data in the same data + structure, it becomes easier for programmers to mistakenly trust unvalidated + data. + metadata: + category: "security" + cwe: "CWE-501" + shortDescription: "Trust Boundary Violation" + security-severity: "Info" + patterns: + - pattern-either: + - patterns: + - pattern: "($H: HttpServletRequest). ... .setAttribute($ARG1, $ARG2)" + - pattern-not: "($H: HttpServletRequest). ... .setAttribute(\"...\", \"...\")" + - patterns: + - pattern: "($H: HttpServletRequest). ... .putValue($ARG1, $ARG2)" + - pattern-not: "($H: HttpServletRequest). ... .putValue(\"...\", \"...\")" + severity: "WARNING" +- id: scala_cors_rule-PermissiveCORS + languages: + - "scala" + message: | + Prior to HTML5, Web browsers enforced the Same Origin Policy which ensures that in order for + JavaScript to access the contents of a Web page, both the JavaScript and the Web page must + originate from the same domain. Without the Same Origin Policy, a malicious website could serve + up JavaScript that loads sensitive information from other websites using a client's + credentials, cull through it, and communicate it back to the attacker. HTML5 makes it possible + for JavaScript to access data across domains if a new HTTP header called + Access-Control-Allow-Origin is defined. With this header, a Web server defines which other + domains are allowed to access its domain using cross-origin requests. However, caution should + be taken when defining the header because an overly permissive CORS policy will allow a + malicious application to communicate with the victim application in an inappropriate way, + leading to spoofing, data theft, relay and other attacks. + metadata: + category: "security" + cwe: "CWE-942" + shortDescription: "Permissive Cross-domain Policy with Untrusted Domains" + technology: + - "scala" + security-severity: "Info" + pattern-either: + - patterns: + - pattern-either: + - pattern: "($RESP:javax.servlet.http.HttpServletResponse).setHeader(\"$HEADER\", + \"$VAL\")" + - pattern: "($RESP:javax.servlet.http.HttpServletResponse).addHeader(\"$HEADER\", + \"$VAL\")" + - metavariable-regex: + metavariable: "$HEADER" + regex: "(?i)(Access-Control-Allow-Origin)" + - metavariable-regex: + metavariable: "$VAL" + regex: "(\\*|null)" + - patterns: + - pattern-inside: | + $REQVAL = ($REQ: javax.servlet.http.HttpServletRequest).getParameter(...) + ... + - pattern-either: + - pattern-inside: |- + ($RESP:javax.servlet.http.HttpServletResponse).setHeader("$HEADER", $REQVAL) + - pattern-inside: |- + ($RESP:javax.servlet.http.HttpServletResponse).addHeader("$HEADER", $REQVAL) + - patterns: + - pattern-either: + - pattern-inside: |- + ($RESP:javax.servlet.http.HttpServletResponse).setHeader("$HEADER",($REQ: javax.servlet.http.HttpServletRequest).getParameter(...)) + - pattern-inside: |- + ($RESP:javax.servlet.http.HttpServletResponse).addHeader("$HEADER",($REQ: javax.servlet.http.HttpServletRequest).getParameter(...)) + severity: "ERROR" +- id: scala_cors_rule-PermissiveCORSInjection + languages: + - "java" + message: | + Prior to HTML5, Web browsers enforced the Same Origin Policy which ensures that in order for + JavaScript to access the contents of a Web page, both the JavaScript and the Web page must + originate from the same domain. Without the Same Origin Policy, a malicious website could serve + up JavaScript that loads sensitive information from other websites using a client's + credentials, cull through it, and communicate it back to the attacker. HTML5 makes it possible + for JavaScript to access data across domains if a new HTTP header called + Access-Control-Allow-Origin is defined. With this header, a Web server defines which other + domains are allowed to access its domain using cross-origin requests. However, caution should + be taken when defining the header because an overly permissive CORS policy will allow a + malicious application to communicate with the victim application in an inappropriate way, + leading to spoofing, data theft, relay and other attacks. + metadata: + category: "security" + cwe: "CWE-942" + shortDescription: "Permissive Cross-domain Policy with Untrusted Domains" + technology: + - "java" + security-severity: "Low" + mode: "taint" + pattern-sinks: + - patterns: + - pattern-either: + - pattern: "(HttpServletResponse $RES).setHeader(\"$HEADER\", ...)" + - pattern: "(HttpServletResponse $RES).addHeader(\"$HEADER\", ...)" + - metavariable-regex: + metavariable: "$HEADER" + regex: "(?i)(Access-Control-Allow-Origin)" + pattern-sources: + - pattern: "(HttpServletRequest $REQ).getParameter(...)" + severity: "ERROR" +- id: scala_crypto_rule-BlowfishKeySize + languages: + - "scala" + message: | + A small key size makes the ciphertext vulnerable to brute force attacks. At least 128 bits of + entropy should be used when generating the key if use of Blowfish is required. + metadata: + category: "security" + cwe: "CWE-326" + shortDescription: "Inadequate Encryption Strength" + technology: + - "scala" + security-severity: "Medium" + patterns: + - pattern-inside: | + $KEYGEN = javax.crypto.KeyGenerator.getInstance("Blowfish", ...); + ... + $KEYGEN.init($KEY_SIZE); + - metavariable-comparison: + comparison: "$KEY_SIZE < 128" + metavariable: "$KEY_SIZE" + severity: "WARNING" +- id: scala_crypto_rule-CipherDESInsecure + languages: + - "scala" + message: | + DES is considered strong ciphers for modern applications. Currently, NIST recommends the usage + of AES block ciphers instead of DES. + metadata: + category: "security" + cwe: "CWE-326" + shortDescription: "Inadequate Encryption Strength" + technology: + - "scala" + security-severity: "Medium" + patterns: + - pattern-inside: |- + javax.crypto.Cipher.getInstance("$ALG") + - metavariable-regex: + metavariable: "$ALG" + regex: "^(DES)/.*" + severity: "WARNING" +- id: scala_crypto_rule-CipherDESedeInsecure + languages: + - "scala" + message: | + Triple DES (also known as 3DES or DESede) is considered strong ciphers for modern + applications. NIST recommends the usage of AES block ciphers instead of 3DES. + metadata: + category: "security" + cwe: "CWE-326" + shortDescription: "Inadequate Encryption Strength" + technology: + - "scala" + security-severity: "Medium" + patterns: + - pattern-inside: |- + javax.crypto.Cipher.getInstance("$ALG") + - metavariable-regex: + metavariable: "$ALG" + regex: "^(DESede)/.*" + severity: "WARNING" +- id: scala_crypto_rule-CipherECBMode + languages: + - "scala" + message: | + An authentication cipher mode which provides better confidentiality of the encrypted data + should be used instead of Electronic Code Book (ECB) mode, which does not provide good + confidentiality. Specifically, ECB mode produces the same output for the same input each time. + This allows an attacker to intercept and replay the data. + metadata: + category: "security" + cwe: "CWE-326" + shortDescription: "Inadequate Encryption Strength" + technology: + - "scala" + security-severity: "Medium" + patterns: + - pattern-inside: |- + javax.crypto.Cipher.getInstance("...") + - pattern-regex: "(AES|DES(ede)?)(/ECB/*)" + severity: "ERROR" +- id: scala_crypto_rule-CipherIntegrity + languages: + - "scala" + message: | + The ciphertext produced is susceptible to alteration by an adversary. This mean that the + cipher provides no way to detect that the data has been tampered with. If the ciphertext can be + controlled by an attacker, it could be altered without detection. + metadata: + category: "security" + cwe: "CWE-353" + shortDescription: "Missing Support for Integrity Check" + technology: + - "scala" + security-severity: "Medium" + patterns: + - pattern-inside: |- + javax.crypto.Cipher.getInstance("...") + - pattern-either: + - pattern-regex: "(/CBC/PKCS5Padding)" + - pattern-regex: "(AES|DES(ede)?)(/ECB/*)" + - pattern-regex: "(AES|DES(ede)?)(/CBC/*)" + - pattern-regex: "(AES|DES(ede)?)(/OFB/*)" + - pattern-regex: "(AES|DES(ede)?)(/CTR/*)" + - pattern-not-regex: ".*/(CCM|CWC|OCB|EAX|GCM)/.*" + - pattern-not-regex: "^(RSA)/.*" + - pattern-not-regex: "^(ECIES)$" + severity: "ERROR" +- id: scala_crypto_rule-CipherPaddingOracle + languages: + - "scala" + message: | + This specific mode of CBC with PKCS5Padding is susceptible to padding oracle attacks. An + adversary could potentially decrypt the message if the system exposed the difference between + plaintext with invalid padding or valid padding. The distinction between valid and invalid + padding is usually revealed through distinct error messages being returned for each condition. + metadata: + category: "security" + cwe: "CWE-696" + shortDescription: "Incorrect Behavior Order" + technology: + - "scala" + security-severity: "Medium" + patterns: + - pattern-inside: |- + javax.crypto.Cipher.getInstance("...") + - pattern-regex: "(/CBC/PKCS5Padding)" + - pattern-not-regex: "^(RSA)/.*" + - pattern-not-regex: "^(ECIES)$" + severity: "ERROR" +- id: scala_crypto_rule-CustomMessageDigest + languages: + - "scala" + message: | + Implementing a custom MessageDigest is error-prone. National Institute of Standards and + Technology(NIST) recommends the use of SHA-224, SHA-256, SHA-384, SHA-512, SHA-512/224, or + SHA-512/256. + metadata: + category: "security" + cwe: "CWE-327" + shortDescription: "Use of a Broken or Risky Cryptographic Algorithm" + technology: + - "scala" + security-severity: "Medium" + patterns: + - pattern: | + class $CLAZZ extends java.security.MessageDigest(...) { + ... + } + severity: "WARNING" +- id: scala_crypto_rule-DefaultHTTPClient + patterns: + - pattern: "new org.apache.http.impl.client.DefaultHttpClient(...)" + message: | + DefaultHttpClient with default constructor is not compatible with TLS 1.2 + languages: + - "scala" + severity: "WARNING" + metadata: + shortDescription: "Inadequate encryption strength" + category: "security" + cwe: "CWE-326" + technology: + - "scala" + security-severity: "Info" +- id: scala_crypto_rule-HazelcastSymmetricEncryption + languages: + - "scala" + message: | + The network communications for Hazelcast is configured to use a symmetric cipher (probably DES + or Blowfish). Those ciphers alone do not provide integrity or secure authentication. The use of + asymmetric encryption is preferred. + metadata: + category: "security" + cwe: "CWE-326" + shortDescription: "Inadequate Encryption Strength" + technology: + - "scala" + security-severity: "Medium" + patterns: + - pattern: "new com.hazelcast.config.SymmetricEncryptionConfig()" + severity: "WARNING" +- id: scala_crypto_rule-InsufficientKeySizeRsa + languages: + - "scala" + message: | + Detected an insufficient key size for DSA. NIST recommends a key size + of 2048 or higher. + metadata: + category: "security" + cwe: "CWE-326" + shortDescription: "Inadequate Encryption Strength" + security-severity: "Medium" + patterns: + - pattern-either: + - patterns: + - pattern-inside: | + $GEN = KeyPairGenerator.getInstance($ALG, ...); + ... + - pattern-either: + - pattern: "$VAR.initialize($SIZE, ...)" + - pattern: "new java.security.spec.RSAKeyGenParameterSpec($SIZE, ...)" + - metavariable-comparison: + comparison: "$SIZE < 2048" + metavariable: "$SIZE" + - metavariable-regex: + metavariable: "$ALG" + regex: "\"(RSA|DSA)\"" + severity: "WARNING" +- id: scala_crypto_rule-NullCipher + languages: + - "scala" + message: | + The NullCipher implements the Cipher interface by returning ciphertext identical to the + supplied plaintext. In a few contexts, such as testing, a NullCipher may be appropriate. Avoid + using the NullCipher. Its accidental use can introduce a significant confidentiality risk. + metadata: + category: "security" + cwe: "CWE-327" + shortDescription: "Use of a Broken or Risky Cryptographic Algorithm" + technology: + - "scala" + security-severity: "Medium" + pattern: "new javax.crypto.NullCipher()" + severity: "WARNING" +- id: scala_crypto_rule-RsaNoPadding + languages: + - "scala" + message: | + The software uses the RSA algorithm but does not incorporate Optimal Asymmetric + Encryption Padding (OAEP), which might weaken the encryption. + metadata: + cwe: "CWE-780" + shortDescription: "Use of RSA Algorithm without OAEP" + security-severity: "Medium" + category: "security" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + patterns: + - pattern: "javax.crypto.Cipher.getInstance(\"$ALG\",...)" + - metavariable-regex: + metavariable: "$ALG" + regex: ".*NoPadding.*" + severity: "WARNING" +- id: scala_crypto_rule-WeakMessageDigest + languages: + - "scala" + message: | + DES is considered strong ciphers for modern applications. Currently, NIST recommends the usage + of AES block ciphers instead of DES. + metadata: + category: "security" + cwe: "CWE-326" + shortDescription: "Inadequate Encryption Strength" + technology: + - "scala" + security-severity: "Medium" + patterns: + - pattern-either: + - pattern: "MessageDigest.getInstance(\"$ALG\", ...)" + - pattern: "Signature.getInstance(\"$ALG\", ...)" + - metavariable-regex: + metavariable: "$ALG" + regex: "(.*(MD5|MD4|MD2|SHA1|SHA-1).*)" + severity: "WARNING" +- id: scala_crypto_rule-WeakTLSProtocol + languages: + - "scala" + message: | + A HostnameVerifier that accept any host are often use because of certificate + reuse on many hosts. As a consequence, this is vulnerable to Man-in-the-middleattacks + attacks since the client will trust any certificate. + metadata: + category: "security" + cwe: "CWE-295" + shortDescription: "Improper Certificate Validation" + security-severity: "Medium" + patterns: + - pattern-either: + - pattern: "new org.apache.http.impl.client.DefaultHttpClient()" + - pattern: "javax.net.ssl.SSLContext.getInstance(\"SSL\")" + - patterns: + - pattern-inside: | + import javax.net.ssl._ + ... + - pattern: "SSLContext.getInstance(\"SSL\")" + severity: "WARNING" +- id: scala_endpoint_rule-JaxRsEndpoint + languages: + - "scala" + message: | + This method is part of a REST Web Service (JSR311). The security of this web service should be + analyzed. For example: + - Authentication, if enforced, should be tested. + - Access control, if enforced, should be tested. + - The inputs should be tracked for potential vulnerabilities. + - The communication should ideally be over SSL. + - If the service supports writes (e.g., via POST), its vulnerability to CSRF should be + investigated. + metadata: + category: "security" + cwe: "CWE-348" + shortDescription: "Use of less trusted source" + technology: + - "scala" + security-severity: "Medium" + mode: "taint" + pattern-sinks: + - pattern: "<...$VAR...>" + pattern-sources: + - patterns: + - pattern-inside: | + @javax.ws.rs.Path("...") + def $FUNC(..., $VAR: $TYPE, ...) = ... + - pattern: "$VAR" + severity: "INFO" +- id: scala_endpoint_rule-JaxWsEndpoint + languages: + - "scala" + message: | + This method is part of a SOAP Web Service (JSR224). The security of this web service should be + analyzed. For example: + - Authentication, if enforced, should be tested. + - Access control, if enforced, should be tested. + - The inputs should be tracked for potential vulnerabilities. + - The communication should ideally be over SSL. + metadata: + category: "security" + owasp: + - "A7:2017-Cross-Site Scripting (XSS)" + - "A03:2021-Injection" + cwe: "CWE-348" + shortDescription: "Use of less trusted source" + technology: + - "scala" + security-severity: "Info" + mode: "taint" + pattern-sinks: + - pattern: "<...$VAR...>" + pattern-sources: + - patterns: + - pattern-inside: | + @javax.jws.WebMethod(...) + def $FUNC(..., $VAR: $TYPE, ...) = ... + - pattern: "$VAR" + severity: "INFO" +- id: scala_endpoint_rule-UnencryptedSocket + languages: + - "scala" + message: | + Beyond using an SSL socket, you need to make sure your use of SSLSocketFactory + does all the appropriate certificate validation checks to make sure you are not + subject to man-in-the-middle attacks. Please read the OWASP Transport Layer + Protection Cheat Sheet for details on how to do this correctly. + metadata: + cwe: "CWE-319" + shortDescription: "Cleartext transmission of sensitive information" + security-severity: "Info" + owasp: + - "A3:2017-Sensitive Data Exposure" + - "A02:2021-Cryptographic Failures" + category: "security" + patterns: + - pattern: "new java.net.Socket(...)" + severity: "WARNING" +- id: scala_endpoint_rule-UnvalidatedRedirect + languages: + - "scala" + message: | + Unvalidated redirects occur when an application redirects a user to a + destination URL specified by a user supplied parameter that is not validated. + Such vulnerabilities can be used to facilitate phishing attacks. + metadata: + category: "security" + cwe: "CWE-601" + shortDescription: "URL Redirection to Untrusted Site ('Open Redirect')" + security-severity: "Info" + patterns: + - pattern-either: + - patterns: + - pattern: "($REQ: HttpServletResponse).sendRedirect(...)" + - pattern-not: "($REQ: HttpServletResponse).sendRedirect(\"...\")" + - patterns: + - pattern: "($REQ: HttpServletResponse).addHeader(...)" + - pattern-not: "($REQ: HttpServletResponse).addHeader(\"...\", \"...\")" + - patterns: + - pattern: "($REQ: HttpServletResponse).encodeURL(...)" + - pattern-not: "($REQ: HttpServletResponse).encodeURL(\"...\")" + - patterns: + - pattern: "($REQ: HttpServletResponse).encodeRedirectUrl(...)" + - pattern-not: "($REQ: HttpServletResponse).encodeRedirectUrl(\"...\")" + severity: "ERROR" +- id: scala_endpoint_rule-WeakHostNameVerification + languages: + - "scala" + message: | + A HostnameVerifier that accept any host are often use because of certificate + reuse on many hosts. As a consequence, this is vulnerable to Man-in-the-middle + attacks since the client will trust any certificate. + metadata: + category: "security" + cwe: "CWE-295" + shortDescription: "Improper Certificate Validation" + security-severity: "Info" + patterns: + - pattern-either: + - patterns: + - pattern-inside: | + class $V extends HostnameVerifier { + ... + } + - pattern-either: + - pattern: "def verify(...) = true" + - pattern: | + def verify(...) = { + return true + } + - patterns: + - pattern-inside: | + class $V extends X509TrustManager { + ... + } + - pattern-either: + - pattern: "def checkClientTrusted(...): Unit = {}" + - pattern: "def checkServerTrusted(...): Unit = {}" + - pattern: "def checkClientTrusted(...) = {}" + - pattern: "def checkServerTrusted(...) = {}" + - pattern: "def getAcceptedIssuers(): Array[X509Certificate] = null" + - pattern: "def getAcceptedIssuers(): Array[X509Certificate] = {}" + severity: "WARNING" +- id: scala_file_rule-FileUploadFileName + languages: + - "scala" + message: | + The filename provided by the FileUpload API can be tampered with by the client to reference + unauthorized files. The provided filename should be properly validated to ensure it's properly + structured, contains no unauthorized path characters (e.g., / \), and refers to an authorized + file. + metadata: + category: "security" + cwe: "CWE-22" + shortDescription: "Improper limitation of a pathname to a restricted directory + ('Path Traversal')" + technology: + - "scala" + owasp: + - "A5:2017-Broken Access Control" + - "A01:2021-Broken Access Control" + security-severity: "Info" + patterns: + - pattern: | + def $FUNC (..., $REQ: HttpServletRequest, ... ) = { + ... + val $FILES = ($SFU: ServletFileUpload).parseRequest($REQ) + ... + for ($FILE <- $FILES.asScala) { + ... + } + } + - pattern: "$ITEM.getName()" + severity: "WARNING" +- id: scala_file_rule-FilenameUtils + languages: + - "scala" + message: | + A file is opened to read its content. The filename comes from an input + parameter. If an unfiltered parameter is passed to this file API, files from an + arbitrary filesystem location could be read. + metadata: + category: "security" + cwe: "CWE-22" + shortDescription: "Improper limitation of a pathname to a restricted directory + ('Path Traversal')" + technology: + - "scala" + owasp: + - "A5:2017-Broken Access Control" + - "A01:2021-Broken Access Control" + security-severity: "Medium" + pattern-either: + - patterns: + - pattern-inside: | + import org.apache.commons.io.FilenameUtils._ + ... + - pattern-either: + - pattern: "normalize(...)" + - pattern: "getExtension(...)" + - pattern: "isExtensions(...)" + - pattern: "isExtension(...)" + - pattern: "getName(...)" + - pattern: "getBaseName(...)" + - patterns: + - pattern-either: + - pattern: "org.apache.commons.io.FilenameUtils.normalize(...)" + - pattern: "org.apache.commons.io.FilenameUtils.getExtension(...)" + - pattern: "org.apache.commons.io.FilenameUtils.isExtensions(...)" + - pattern: "org.apache.commons.io.FilenameUtils.isExtension(...)" + - pattern: "org.apache.commons.io.FilenameUtils.getName(...)" + - pattern: "org.apache.commons.io.FilenameUtils.getBaseName(...)" + severity: "WARNING" +- id: scala_form_rule-FormValidate + languages: + - "scala" + message: | + Form inputs should have minimal input validation. Preventive validation helps provide defense + in depth against a variety of risks. + metadata: + category: "security" + cwe: "CWE-1289" + shortDescription: "Improper validation of unsafe equivalence in input" + security-severity: "Info" + patterns: + - pattern-inside: | + class $CLASS extends $SC { + ... + } + - metavariable-regex: + metavariable: "$SC" + regex: "(ActionForm|ValidatorForm)" + - pattern-not: "public void validate() { ... }" + severity: "WARNING" +- id: scala_inject_rule-AWSQueryInjection + languages: + - "scala" + message: | + Constructing SimpleDB queries containing user input can allow an attacker to view unauthorized + records. + metadata: + category: "security" + cwe: "CWE-943" + shortDescription: "Improper Neutralization of Special Elements in Data Query Logic" + technology: + - "scala" + security-severity: "Info" + mode: "taint" + pattern-sinks: + - pattern: "new com.amazonaws.services.simpledb.model.SelectRequest($QUERY, ...);" + - patterns: + - pattern-inside: | + $DB.select(($SR: com.amazonaws.services.simpledb.model.SelectRequest).withSelectExpression($QUERY,...)); + - pattern: "$QUERY" + - metavariable-pattern: + metavariable: "$DB" + pattern-either: + - pattern: "($DB: com.amazonaws.services.simpledb.AmazonSimpleDB)" + - pattern: "($DB: com.amazonaws.services.simpledb.AmazonSimpleDBClient)" + pattern-sources: + - patterns: + - pattern-inside: | + def $FUNC(..., $REQ: HttpServletRequest, ...): $TYPE = { + ... + } + - pattern: "$REQ" + - patterns: + - pattern-inside: | + def $FUNC(..., $X: $TYPE, ...): $RET_TYPE = { + ... + $QUERY = <...$X...> + ... + } + - pattern: "$QUERY" + severity: "ERROR" +- id: scala_inject_rule-BeanPropertyInjection + languages: + - "scala" + message: | + An attacker can set arbitrary bean properties that can compromise system integrity. An + attacker can leverage this functionality to access special bean properties like + class.classLoader that will allow them to override system properties and potentially execute + arbitrary code. + metadata: + category: "security" + cwe: "CWE-15" + shortDescription: "External Control of System or Configuration Setting" + technology: + - "scala" + security-severity: "Info" + patterns: + - pattern-inside: |- + def $FUNC(..., $REQ: HttpServletRequest, ...): $TYPE = { ... } + - pattern-either: + - pattern: | + $MAP.put(..., $REQ.getParameter(...)) + ... + $BEAN_UTIL.populate(..., $MAP) + - pattern: | + while (...) { + ... + $MAP.put(..., $REQ.getParameterValues(...). ...) + } + ... + $BEAN_UTIL.populate(..., $MAP) + - metavariable-pattern: + metavariable: "$BEAN_UTIL" + pattern-either: + - pattern: "(BeanUtilsBean $B)" + - pattern: "new BeanUtilsBean()" + - pattern: "org.apache.commons.beanutils.BeanUtils" + severity: "ERROR" +- id: scala_inject_rule-CLRFInjectionLogs + languages: + - "scala" + message: | + When data from an untrusted source is put into a logger and not neutralized correctly, an + attacker could forge log entries or include malicious content. Inserted false entries could be + used to skew statistics, distract the administrator or even to implicate another party in the + commission of a malicious act. If the log file is processed automatically, the attacker can + render the file unusable by corrupting the format of the file or injecting unexpected + characters. An attacker may also inject code or other commands into the log file and take + advantage of a vulnerability in the log processing utility (e.g. command injection or XSS). + metadata: + category: "security" + cwe: "CWE-93" + shortDescription: "Improper Neutralization of CRLF Sequences ('CRLF Injection')" + technology: + - "scala" + security-severity: "Info" + mode: "taint" + pattern-sanitizers: + - patterns: + - pattern-inside: |- + $STR.replaceAll("$REPLACE_CHAR", "$REPLACE"); + - pattern: "$STR" + - metavariable-regex: + metavariable: "$REPLACE_CHAR" + regex: "(.*\\\\r\\\\n.*)" + - metavariable-regex: + metavariable: "$REPLACE" + regex: "(?!(\\\\r\\\\n))" + - pattern: "org.owasp.encoder.Encode.forUriComponent(...)" + - pattern: "org.owasp.encoder.Encode.forUri(...)" + - pattern: "java.net.URLEncoder.encode(..., $CHARSET)" + pattern-sinks: + - patterns: + - patterns: + - pattern: "$LOGGER.$METHOD(...,<...$TAINTED...>,...)" + - focus-metavariable: "$TAINTED" + - metavariable-regex: + metavariable: "$METHOD" + regex: "(log|logp|logrb|entering|exiting|fine|finer|finest|info|debug|trace|warn|warning|config|error|severe)" + - metavariable-pattern: + metavariable: "$LOGGER" + pattern-either: + - pattern: "Logger" + - pattern: "log" + - pattern: "logger" + - pattern: "org.pmw.tinylog.Logger" + - pattern: "org.apache.log4j.Logger" + - pattern: "org.apache.logging.log4j.Logger" + - pattern: "org.slf4j.Logger" + - pattern: "org.apache.commons.logging.Log" + - pattern: "java.util.logging.Logger" + pattern-sources: + - patterns: + - pattern-inside: | + def $FUNC(..., $REQ: HttpServletRequest, ...) : $TYPE = { + ... + } + - pattern: "$REQ.getParameter(...)" + severity: "ERROR" +- id: scala_inject_rule-CommandInjection + languages: + - "scala" + message: | + The highlighted API is used to execute a system command. If unfiltered input is passed to this + API, it can lead to arbitrary command execution. + metadata: + category: "security" + cwe: "CWE-78" + shortDescription: "Improper Neutralization of Special Elements used in an OS Command + ('OS Command Injection')" + technology: + - "scala" + security-severity: "Info" + pattern-either: + - patterns: + - pattern-inside: | + def $FUNC(..., $PARAM: String, ...): $TYPE = { + ... + } + - pattern-inside: | + val $RT = Runtime.getRuntime + ... + - pattern-either: + - pattern: "$RT.exec($PARAM)" + - pattern: | + var $CMDARR = new Array[String]("$SHELL",...,$PARAM,...) + ... + $RT.exec($CMDARR,...) + - pattern: "$RT.exec(Array[String](\"$SHELL\",...,$PARAM,...), ...)" + - pattern: "$RT.exec(java.util.String.format(\"...\", ...,$PARAM,...))" + - pattern: "$RT.exec(($A: String) + ($B: String))" + - metavariable-regex: + metavariable: "$SHELL" + regex: "(/.../)?(sh|bash|ksh|csh|tcsh|zsh)$" + - pattern-not: "$RT.exec(\"...\",\"...\",\"...\",...)" + - pattern-not: "$RT.exec(new Array[String](\"...\",\"...\",\"...\",...),...)" + - patterns: + - pattern-inside: | + def $FUNC(...,$PARAM: String, ...): $TYPE = { + ... + } + - pattern-inside: | + val $PB = new ProcessBuilder() + ... + - pattern-either: + - pattern: "$PB.command($PARAM,...)" + - patterns: + - pattern-either: + - pattern: "$PB.command(\"$SHELL\",...,$PARAM,...)" + - pattern: | + var $CMDARR = java.util.Arrays.asList("$SHELL",...,$PARAM,...) + ... + $PB.command($CMDARR,...) + - pattern: "$PB.command(java.util.Arrays.asList(\"$SHELL\",...,$PARAM,...),...)" + - pattern: "$PB.command(java.util.String.format(\"...\", ...,$PARAM,...))" + - pattern: "$PB.command(($A: String) + ($B: String))" + - metavariable-regex: + metavariable: "$SHELL" + regex: "(/.../)?(sh|bash|ksh|csh|tcsh|zsh)$" + - pattern-not: "$PB.command(\"...\",\"...\",\"...\",...)" + - pattern-not: | + $PB.command(java.util.Arrays.asList("...","...","...",...)) + severity: "WARNING" +- id: scala_inject_rule-CustomInjection + languages: + - "scala" + message: | + The method identified is susceptible to injection. The input should be validated and properly + escaped. + metadata: + category: "security" + cwe: "CWE-89" + shortDescription: "Improper Neutralization of Special Elements used in an SQL + Command ('SQL Injection')" + technology: + - "scala" + security-severity: "Low" + patterns: + - pattern-either: + - pattern-inside: | + val $ST = connection.createStatement + ... + - pattern-either: + - pattern: | + val $QUERY = ... + $VAR + ... + ... + $ST.executeQuery($QUERY) + - pattern: | + val $QUERY = ... + $VAR + ... + $ST.executeQuery($QUERY) + - pattern: | + val $QUERY = String.format("...",...,$VAR,...) + ... + $ST.executeQuery($QUERY) + - pattern: "$ST.executeQuery(($SB: StringBuilder).toString())" + - pattern: "$ST.executeQuery(... + $VAR + ...)" + - pattern: "$ST.executeQuery(... + $VAR)" + - pattern: "$ST.executeQuery(...,String.format(\"...\",...,$VAR,...), ...)" + severity: "WARNING" +- id: scala_inject_rule-CustomInjectionSQLString + languages: + - "scala" + message: | + The method identified is susceptible to injection. The input should be validated and properly + escaped. + metadata: + category: "security" + cwe: "CWE-89" + shortDescription: "Improper Neutralization of Special Elements used in an SQL + Command ('SQL Injection')" + technology: + - "scala" + security-severity: "High" + patterns: + - pattern-inside: | + def $FOO(..., $SQLIN: String, ...): $TYPE = { + ... + } + - pattern-either: + - pattern: | + "$SQL_STR" + $SQLIN + - pattern: "String.format(\"$SQL_STR\", ... + $SQLIN + ...)" + - pattern: | + "$SQL_STR".concat(...) + - pattern: "(StringBuilder $BUILDER). ... .append(\"$SQL_STR\")" + - patterns: + - pattern-inside: | + StringBuilder $BUILDER = new StringBuilder(... + "$SQL_STR" + ...); + ... + - pattern: "$BUILDER.append(...)" + - pattern-not: "$BUILDER.append(\"...\")" + - patterns: + - pattern-inside: | + $QUERY = "$SQL_STR"; + ... + - pattern: "$QUERY += ..." + - metavariable-regex: + metavariable: "$SQL_STR" + regex: "(?i)(select|insert|create|update|alter|delete|drop)\\b" + severity: "WARNING" +- id: scala_inject_rule-ELInjection + languages: + - "scala" + message: | + An expression is built with a dynamic value. The source of the value(s) should be verified to + avoid that unfiltered values fall into this risky code evaluation. + metadata: + category: "security" + cwe: "CWE-94" + shortDescription: "Improper Control of Generation of Code ('Code Injection')" + technology: + - "scala" + security-severity: "High" + patterns: + - pattern-inside: | + import javax.el._ + ... + - pattern-either: + - pattern-inside: | + def $FUNC(..., $EXPR: String, ...) : $TYPE = { + ... + } + - pattern-inside: | + def $FUNC(..., $EXPR: String, ...) = { + ... + } + - pattern-either: + - pattern: "$X.createValueExpression(..., $EXPR, ...)" + - pattern: "$X.createMethodExpression(..., $EXPR, ...)" + severity: "WARNING" +- id: scala_inject_rule-FileDisclosure + languages: + - "scala" + message: | + Constructing a server-side redirect path with user input could allow an + attacker to download application binaries (including application classes or + jar files) or view arbitrary files within protected directories. + metadata: + category: "security" + cwe: "CWE-552" + shortDescription: "Files or Directories Accessible to External Parties" + security-severity: "Info" + mode: "taint" + pattern-sinks: + - patterns: + - pattern: "new org.springframework.web.servlet.ModelAndView($FST)" + - pattern: "$FST" + - patterns: + - pattern: "new org.springframework.web.servlet.ModelAndView($FST, $SND)" + - pattern: "$FST" + - patterns: + - pattern: "new org.springframework.web.servlet.ModelAndView($FST, $SND, $TRD)" + - pattern: "$FST" + - patterns: + - pattern: "new org.apache.struts.action.ActionForward($FST)" + - pattern: "$FST" + - patterns: + - pattern: "new org.apache.struts.action.ActionForward($FST, $SND)" + - pattern: "$FST" + - patterns: + - pattern: "new org.apache.struts.action.ActionForward($FST, $SND, $TRD)" + - pattern: "$SND" + - patterns: + - pattern: "new org.apache.struts.action.ActionForward($FST, $SND, $TRD)" + - pattern: "$TRD" + - patterns: + - pattern-inside: | + $ACTION = new org.apache.struts.action.ActionForward() + ... + - pattern: "$ACTION.setPath(...)" + - patterns: + - pattern-inside: | + $MVC = new org.springframework.web.servlet.ModelAndView() + ... + - pattern: "$MVC.setViewName(...);" + - patterns: + - pattern-inside: | + $REQ = $HTTP.getRequestDispatcher(...) + ... + - pattern-either: + - pattern: "$REQ.include($FST, $SND)" + - pattern: "$REQ.forward($FST, $SND)" + pattern-sources: + - pattern: "($VAR: javax.servlet.http.HttpServletRequest).getParameter(...)" + severity: "ERROR" +- id: scala_inject_rule-HttpParameterPollution + languages: + - "scala" + message: | + Concatenating unvalidated user input into a URL can allow an attacker to override the value of + a request parameter. Attacker may be able to override existing parameter values, inject a new + parameter or exploit variables out of a direct reach. HTTP Parameter Pollution (HPP) attacks + consist of injecting encoded query string delimiters into other existing parameters. If a web + application does not properly sanitize the user input, a malicious user may compromise the + logic of the application to perform either client-side or server-side attacks. + metadata: + category: "security" + cwe: "CWE-88" + shortDescription: "Improper Neutralization of Argument Delimiters in a Command + ('Argument Injection')" + technology: + - "scala" + security-severity: "Info" + mode: "taint" + pattern-sanitizers: + - pattern: "java.net.URLEncoder.encode(...)" + - pattern: "com.google.common.net.UrlEscapers.urlPathSegmentEscaper().escape(...)" + pattern-sinks: + - pattern: "new org.apache.http.client.methods.HttpGet(...)" + - pattern: "new org.apache.commons.httpclient.methods.GetMethod(...)" + - pattern: "($GM: org.apache.commons.httpclient.methods.GetMethod).setQueryString(...)" + pattern-sources: + - pattern: "($REQ: HttpServletRequest ).getParameter(...)" + severity: "ERROR" +- id: scala_inject_rule-LDAPInjection + languages: + - "scala" + message: | + Just like SQL, all inputs passed to an LDAP query need to be passed in safely. Unfortunately, + LDAP doesn't have prepared statement interfaces like SQL. Therefore, the primary defense + against LDAP injection is strong input validation of any untrusted data before including it in + an LDAP query. + metadata: + category: "security" + cwe: "CWE-90" + shortDescription: "Improper Neutralization of Special Elements used in an LDAP + Query ('LDAP Injection')" + technology: + - "scala" + security-severity: "Medium" + patterns: + - pattern-either: + - pattern-inside: | + def $FUNC(..., $VAR: String, ...): $TYPE = { + ... + } + - pattern-inside: | + def $FUNC(..., $X: String, ...): $TYPE = { + ... + $VAR = ... + $X; + ... + } + - pattern-either: + - pattern: "($P: java.util.Properties).put($KEY, $VAR)" + - pattern: "$CTX.lookup(..., $VAR, ...)" + - pattern: "$CTX.search(..., $VAR, ...)" + - pattern: "$CTX.list(..., $VAR, ...)" + - metavariable-pattern: + metavariable: "$CTX" + pattern-either: + - pattern: "($CTX: javax.naming.directory.DirContext)" + - pattern: "($CTX: javax.naming.directory.Context)" + - pattern: "($CTX: javax.naming.Context)" + - pattern: "($CTX: javax.naming.directory.InitialDirContext)" + - pattern: "($CTX: javax.naming.ldap.LdapContext)" + - pattern: "($CTX: com.unboundid.ldap.sdk.LDAPConnection)" + - pattern: "($CTX: javax.naming.event.EventDirContext)" + - pattern: "($CTX: com.sun.jndi.ldap.LdapCtx)" + - pattern: "($CTX: org.springframework.ldap.core.LdapTemplate)" + - pattern: "($CTX: org.springframework.ldap.core.LdapOperations)" + severity: "WARNING" +- id: scala_inject_rule-OgnlInjection + patterns: + - pattern-either: + - pattern-inside: | + def $FUNC(..., $VAR: String, ...): $TYPE = { + ... + } + - pattern-inside: | + def $FUNC(..., $VAR: Map[$K,$V], ...): $TYPE = { + ... + } + - pattern-inside: | + def $FUNC(..., $VAR: java.util.HashMap[$K,$V], ...): $TYPE = { + ... + } + - pattern-either: + - pattern: "com.opensymphony.xwork2.util.TextParseUtil.translateVariables(..., + $VAR, ...)" + - pattern: "com.opensymphony.xwork2.util.TextParseUtil.translateVariablesCollection(..., + $VAR, ...)" + - pattern: "com.opensymphony.xwork2.util.TextParseUtil.shallBeIncluded(..., $VAR, + ...)" + - pattern: "com.opensymphony.xwork2.util.TextParseUtil.commaDelimitedStringToSet(..., + $VAR, ...)" + - pattern: "($P:com.opensymphony.xwork2.util.TextParser).evaluate(..., $VAR, ...)" + - pattern: "($P:com.opensymphony.xwork2.util.OgnlTextParser).evaluate(..., $VAR, + ...)" + - pattern: "($P:com.opensymphony.xwork2.ognl.OgnlReflectionProvider).getGetMethod(..., + $VAR, ...)" + - pattern: "($P:com.opensymphony.xwork2.ognl.OgnlReflectionProvider).getSetMethod(..., + $VAR, ...)" + - pattern: "($P:com.opensymphony.xwork2.ognl.OgnlReflectionProvider).getField(..., + $VAR, ...)" + - pattern: "($P:com.opensymphony.xwork2.ognl.OgnlReflectionProvider).setProperties(..., + $VAR, ...)" + - pattern: "($P:com.opensymphony.xwork2.ognl.OgnlReflectionProvider).setProperty(...,$VAR, + ...)" + - pattern: "($P:com.opensymphony.xwork2.ognl.OgnlReflectionProvider).getValue(...,$VAR, + ...)" + - pattern: "($P:com.opensymphony.xwork2.ognl.OgnlReflectionProvider).setValue(...,$VAR, + ...)" + - pattern: "($P:com.opensymphony.xwork2.util.reflection.ReflectionProvider).getGetMethod(..., + $VAR, ...)" + - pattern: "($P:com.opensymphony.xwork2.util.reflection.ReflectionProvider).getSetMethod(..., + $VAR, ...)" + - pattern: "($P:com.opensymphony.xwork2.util.reflection.ReflectionProvider).getField(..., + $VAR, ...)" + - pattern: "($P:com.opensymphony.xwork2.util.reflection.ReflectionProvider).setProperties(..., + $VAR, ...)" + - pattern: "($P:com.opensymphony.xwork2.util.reflection.ReflectionProvider).setProperty(..., + $VAR, ...)" + - pattern: "($P:com.opensymphony.xwork2.util.reflection.ReflectionProvider).getValue(..., + $VAR, ...)" + - pattern: "($P:com.opensymphony.xwork2.util.reflection.ReflectionProvider).setValue(..., + $VAR, ...)" + - pattern: "($P:com.opensymphony.xwork2.ognl.OgnlUtil).setProperties(..., $VAR, + ...)" + - pattern: "($P:com.opensymphony.xwork2.ognl.OgnlUtil).setProperty(..., $VAR, + ...)" + - pattern: "($P:com.opensymphony.xwork2.ognl.OgnlUtil).getValue(..., $VAR, ...)" + - pattern: "($P:com.opensymphony.xwork2.ognl.OgnlUtil).setValue(..., $VAR, ...)" + - pattern: "($P:com.opensymphony.xwork2.ognl.OgnlUtil).callMethod(..., $VAR, ...)" + - pattern: "($P:com.opensymphony.xwork2.ognl.OgnlUtil).compile(..., $VAR, ...)" + - pattern: "($P:org.apache.struts2.util.VelocityStrutsUtil).evaluate(...)" + - pattern: "org.apache.struts2.util.StrutsUtil.findString(...)" + - pattern: "org.apache.struts2.util.StrutsUtil.findValue(..., $VAL)" + - pattern: "org.apache.struts2.util.StrutsUtil.getText(...)" + - pattern: "org.apache.struts2.util.StrutsUtil.translateVariables(...)" + - pattern: "org.apache.struts2.util.StrutsUtil.makeSelectList(..., $VAR, ...)" + - pattern: "($T:org.apache.struts2.views.jsp.ui.OgnlTool).findValue(..., $VAR, + ...)" + - pattern: "($V:com.opensymphony.xwork2.util.ValueStack).findString(...)" + - pattern: "($V:com.opensymphony.xwork2.util.ValueStack).findValue(..., $VAR, + ...)" + - pattern: "($V:com.opensymphony.xwork2.util.ValueStack).setValue(..., $VAR, ...)" + - pattern: "($V:com.opensymphony.xwork2.util.ValueStack).setParameter(..., $VAR, + ...)" + message: | + "A expression is built with a dynamic value. The source of the value(s) should be verified to + avoid that unfiltered values fall into this risky code evaluation." + languages: + - "scala" + severity: "WARNING" + metadata: + shortDescription: "Expression injection (OGNL)" + category: "security" + cwe: "CWE-917" + technology: + - "scala" + security-severity: "Medium" +- id: scala_inject_rule-PathTraversalIn + languages: + - "scala" + message: | + A file is opened to read its content. The filename comes from an input parameter. If an + unfiltered parameter is passed to this file API, files from an arbitrary filesystem location + could be read. This rule identifies potential path traversal vulnerabilities. In many cases, + the constructed file path cannot be controlled by the user. + metadata: + owasp: + - "A5:2017-Broken Access Control" + - "A01:2021-Broken Access Control" + category: "security" + cwe: "CWE-22" + shortDescription: "Improper limitation of a pathname to a restricted directory + ('Path Traversal')" + technology: + - "scala" + security-severity: "Medium" + patterns: + - pattern-either: + - patterns: + - pattern-inside: | + def $FUNC(...,$ARGS: Array[String], ...): $TYPE = { + ... + } + - pattern-inside: | + $VAR = $ARGS($IDX) + ... + - pattern-inside: | + def $FUNC(...,$VAR: String, ...): $TYPE = { + ... + } + - pattern-not-inside: | + ... + org.apache.commons.io.FilenameUtils.getName($VAR) + ... + - pattern-either: + - patterns: + - pattern-inside: | + $U = new java.net.URI($VAR) + ... + - pattern-either: + - pattern: "new java.io.File($U)" + - pattern: "java.nio.file.Paths.get($U)" + - pattern: "new java.io.RandomAccessFile(..., $VAR,...)" + - pattern: "new java.io.FileReader(<...$VAR...>, ...)" + - pattern: "new javax.activation.FileDataSource(..., $VAR, ...)" + - pattern: "new java.io.FileInputStream(..., $VAR, ...)" + - pattern: "new java.io.File(<...$VAR...>, ...)" + - pattern: "java.nio.file.Paths.get(...,$VAR,...)" + - pattern: "java.io.File.createTempFile(...,$VAR, ...)" + - pattern: "java.io.File.createTempDirectory(...,$VAR,...)" + - pattern: "java.nio.file.Files.createTempFile(..., $VAR, ...)" + - pattern: "java.nio.file.Files.createTempDirectory(..., $VAR, ...)" + - pattern: "scala.io.Source.from(<...$VAR...>)" + - pattern: "scala.io.Source.fromFile(<...$VAR...>)" + - pattern: "scala.io.Source.fromString(<...$VAR...>)" + severity: "ERROR" +- id: scala_inject_rule-PathTraversalOut + languages: + - "scala" + message: | + A file is opened to write to its contents. The filename comes from an input parameter. If an + unfiltered parameter is passed to this file API, files at an arbitrary filesystem location + could be modified. This rule identifies potential path traversal vulnerabilities. In many + cases, the constructed file path cannot be controlled by the user. + metadata: + owasp: + - "A5:2017-Broken Access Control" + - "A01:2021-Broken Access Control" + category: "security" + cwe: "CWE-22" + shortDescription: "Improper limitation of a pathname to a restricted directory + ('Path Traversal')" + technology: + - "scala" + security-severity: "High" + mode: "taint" + pattern-sanitizers: + - pattern: "org.apache.commons.io.FilenameUtils.getName(...)" + pattern-sinks: + - patterns: + - pattern-inside: |- + new java.io.FileWriter($PATH, ...) + - pattern: "$PATH" + - patterns: + - pattern-inside: |- + new java.io.FileOutputStream($PATH, ...) + - pattern: "$PATH" + pattern-sources: + - patterns: + - pattern-inside: | + def $FUNC(..., $ARGS: Array[String], ...): $TYPE = { + ... + } + - pattern: "$ARGS[$IDX]" + - patterns: + - pattern-inside: | + def $FUNC(..., $VAR: String, ...): $TYPE = { + ... + } + - pattern: "$VAR" + severity: "WARNING" +- id: scala_inject_rule-SpotbugsPathTraversalAbsolute + languages: + - "scala" + message: | + "The software uses an HTTP request parameter to construct a pathname that should be within a + restricted directory, but it does not properly neutralize absolute path sequences such as + "/abs/path" that can resolve to a location that is outside of that directory. See + http://cwe.mitre.org/data/definitions/36.html for more information." + metadata: + owasp: + - "A5:2017-Broken Access Control" + - "A01:2021-Broken Access Control" + category: "security" + cwe: "CWE-22" + shortDescription: "Improper limitation of a pathname to a restricted directory + ('Path Traversal')" + technology: + - "scala" + security-severity: "Info" + mode: "taint" + pattern-sanitizers: + - pattern: "org.apache.commons.io.FilenameUtils.getName(...)" + pattern-sinks: + - patterns: + - pattern-inside: | + $U = new java.net.URI($VAR) + - pattern-either: + - pattern-inside: |- + new java.io.File($U) + - pattern-inside: |- + java.nio.file.Paths.get($U) + - pattern: "$VAR" + - patterns: + - pattern-inside: |- + new java.io.RandomAccessFile($INPUT,...) + - pattern: "$INPUT" + - pattern: "new java.io.FileReader(...)" + - pattern: "new javax.activation.FileDataSource(...)" + - pattern: "new java.io.FileInputStream(...)" + - pattern: "new java.io.File(...)" + - pattern: "java.nio.file.Paths.get(...)" + - pattern: "java.io.File.createTempFile(...)" + - pattern: "java.io.File.createTempDirectory(...)" + - pattern: "java.nio.file.Files.createTempFile(...)" + - pattern: "java.nio.file.Files.createTempDirectory(...)" + - patterns: + - pattern-inside: |- + new java.io.FileWriter($PATH, ...) + - pattern: "$PATH" + - patterns: + - pattern-inside: |- + new java.io.FileOutputStream($PATH, ...) + - pattern: "$PATH" + pattern-sources: + - pattern: "($REQ: HttpServletRequest ).getParameter(...)" + severity: "WARNING" +- id: scala_inject_rule-SpotbugsPathTraversalRelative + languages: + - "scala" + message: | + "The software uses an HTTP request parameter to construct a pathname that should be within a + restricted directory, but it does not properly neutralize sequences such as ".." that can + resolve to a location that is outside of that directory. See + http://cwe.mitre.org/data/definitions/23.html for more information." + metadata: + owasp: + - "A5:2017-Broken Access Control" + - "A01:2021-Broken Access Control" + category: "security" + cwe: "CWE-22" + shortDescription: "Improper limitation of a pathname to a restricted directory + ('Path Traversal')" + technology: + - "scala" + security-severity: "Info" + mode: "taint" + pattern-sanitizers: + - pattern: "org.apache.commons.io.FilenameUtils.getName(...)" + pattern-sinks: + - patterns: + - pattern-inside: | + $U = new java.net.URI($VAR) + - pattern-either: + - pattern-inside: |- + new java.io.File($U) + - pattern-inside: |- + java.nio.file.Paths.get($U) + - pattern: "$VAR" + - patterns: + - pattern-inside: |- + new java.io.RandomAccessFile($INPUT,...) + - pattern: "$INPUT" + - pattern: "new java.io.FileReader(...)" + - pattern: "new javax.activation.FileDataSource(...)" + - pattern: "new java.io.FileInputStream(...)" + - pattern: "new java.io.File(...)" + - pattern: "java.nio.file.Paths.get(...)" + - pattern: "java.io.File.createTempFile(...)" + - pattern: "java.io.File.createTempDirectory(...)" + - pattern: "java.nio.file.Files.createTempFile(...)" + - pattern: "java.nio.file.Files.createTempDirectory(...)" + - patterns: + - pattern-inside: |- + new java.io.FileWriter($PATH, ...) + - pattern: "$PATH" + - patterns: + - pattern-inside: |- + new java.io.FileOutputStream($PATH, ...) + - pattern: "$PATH" + pattern-sources: + - patterns: + - pattern-inside: | + $P = ($REQ: HttpServletRequest ).getParameter(...); + ... + - pattern-either: + - pattern: "$P + ..." + - pattern: "... + $P" + severity: "WARNING" +- id: scala_inject_rule-SqlInjection + languages: + - "scala" + message: | + The input values included in SQL queries need to be passed in safely. Bind + variables in prepared statements can be used to easily mitigate the risk of + SQL injection. + metadata: + category: "security" + cwe: "CWE-89" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + shortDescription: "Improper Neutralization of Special Elements used in an SQL + Command ('SQL Injection')" + security-severity: "Medium" + patterns: + - pattern-not-inside: | + $ARG = ... + ... + - pattern-not-inside: | + object $CLAZZ { + ... + $ARG = ... + ... + } + - pattern-not-inside: | + class $CLAZZ { + ... + $ARG = ... + ... + } + - pattern-either: + - patterns: + - pattern: "($PM:javax.jdo.PersistenceManager).newQuery(<...$ARG...>)" + - pattern-not: "($PM:javax.jdo.PersistenceManager).newQuery(\"...\")" + - patterns: + - pattern: "($PM:javax.jdo.PersistenceManager).newQuery(..., <...$ARG...>)" + - pattern-not: "($PM:javax.jdo.PersistenceManager).newQuery(..., \"...\")" + - patterns: + - pattern: "($Q: javax.jdo.Query).setFilter(<...$ARG...>)" + - pattern-not: "($Q: javax.jdo.Query).setFilter(\"...\")" + - patterns: + - pattern: "($Q: javax.jdo.Query).setGrouping(<...$ARG...>)" + - pattern-not: "($Q: javax.jdo.Query).setGrouping(\"...\")" + - patterns: + - pattern: "($Q: javax.jdo.Query).setGrouping(<...$ARG...>)" + - pattern-not: "($Q: javax.jdo.Query).setGrouping(\"...\")" + - patterns: + - pattern: "($H: org.hibernate.criterion.Restrictions).sqlRestriction(<...$ARG...>, + ...)" + - pattern-not: "($H: org.hibernate.criterion.Restrictions).sqlRestriction(\"...\", + ...)" + - patterns: + - pattern: "($S: org.hibernate.Session).createQuery(<...$ARG...>, ...)" + - pattern-not: "($S: org.hibernate.Session).createQuery(\"...\", ...)" + - patterns: + - pattern: "($S: org.hibernate.Session).createSQLQuery(<...$ARG...>, ...)" + - pattern-not: "($S: org.hibernate.Session).createSQLQuery(\"...\", ...)" + - patterns: + - pattern: "($S: java.sql.Statement).executeQuery(<...$ARG...>, ...)" + - pattern-not: "($S: java.sql.Statement).createSQLQuery(\"...\", ...)" + - patterns: + - pattern: "($S: java.sql.Statement).execute(<...$ARG...>, ...)" + - pattern-not: "($S: java.sql.Statement).execute(\"...\", ...)" + - patterns: + - pattern: "($S: java.sql.Statement).executeUpdate(<...$ARG...>, ...)" + - pattern-not: "($S: java.sql.Statement).executeUpdate(\"...\", ...)" + - patterns: + - pattern: "($S: java.sql.Statement).executeLargeUpdate(<...$ARG...>, ...)" + - pattern-not: "($S: java.sql.Statement).executeLargeUpdate(\"...\", ...)" + - patterns: + - pattern: "($S: java.sql.Statement).addBatch(<...$ARG...>, ...)" + - pattern-not: "($S: java.sql.Statement).addBatch(\"...\", ...)" + - patterns: + - pattern: "($S: java.sql.PreparedStatement).executeQuery(<...$ARG...>, ...)" + - pattern-not: "($S: java.sql.PreparedStatement).executeQuery(\"...\", ...)" + - patterns: + - pattern: "($S: java.sql.PreparedStatement).execute(<...$ARG...>, ...)" + - pattern-not: "($S: java.sql.PreparedStatement).execute(\"...\", ...)" + - patterns: + - pattern: "($S: java.sql.PreparedStatement).executeUpdate(<...$ARG...>, ...)" + - pattern-not: "($S: java.sql.PreparedStatement).executeUpdate(\"...\", ...)" + - patterns: + - pattern: "($S: java.sql.PreparedStatement).executeLargeUpdate(<...$ARG...>, + ...)" + - pattern-not: "($S: java.sql.PreparedStatement).executeLargeUpdate(\"...\", + ...)" + - patterns: + - pattern: "($S: java.sql.PreparedStatement).addBatch(<...$ARG...>, ...)" + - pattern-not: "($S: java.sql.PreparedStatement).addBatch(\"...\", ...)" + - patterns: + - pattern: "($S: java.sql.Connection).prepareCall(<...$ARG...>, ...)" + - pattern-not: "($S: java.sql.Connection).prepareCall(\"...\", ...)" + - patterns: + - pattern: "($S: java.sql.Connection).prepareStatement(<...$ARG...>, ...)" + - pattern-not: "($S: java.sql.Connection).prepareStatement(\"...\", ...)" + - patterns: + - pattern: "($S: java.sql.Connection).nativeSQL(<...$ARG...>, ...)" + - pattern-not: "($S: java.sql.Connection).nativeSQL(\"...\", ...)" + - patterns: + - pattern: "new org.springframework.jdbc.core.PreparedStatementCreatorFactory(<...$ARG...>, + ...)" + - pattern-not: "new org.springframework.jdbc.core.PreparedStatementCreatorFactory(\"...\", + ...)" + - patterns: + - pattern: "(org.springframework.jdbc.core.PreparedStatementCreatorFactory $F).newPreparedStatementCreator(<...$ARG...>, + ...)" + - pattern-not: "(org.springframework.jdbc.core.PreparedStatementCreatorFactory + $F).newPreparedStatementCreator(\"...\", ...)" + - patterns: + - pattern: "($O: org.springframework.jdbc.core.JdbcOperations).batchUpdate(<...$ARG...>, + ...)" + - pattern-not: "($O: org.springframework.jdbc.core.JdbcOperations).batchUpdate(\"...\", + ...)" + - patterns: + - pattern: "($O: org.springframework.jdbc.core.JdbcOperations).execute(<...$ARG...>, + ...)" + - pattern-not: "($O: org.springframework.jdbc.core.JdbcOperations).execute(\"...\", + ...)" + - patterns: + - pattern: "($O: org.springframework.jdbc.core.JdbcOperations).query(<...$ARG...>, + ...)" + - pattern-not: "($O: org.springframework.jdbc.core.JdbcOperations).query(\"...\", + ...)" + - patterns: + - pattern: "($O: org.springframework.jdbc.core.JdbcOperations).queryForList(<...$ARG...>, + ...)" + - pattern-not: "($O: org.springframework.jdbc.core.JdbcOperations).queryForList(\"...\", + ...)" + - patterns: + - pattern: "($O: org.springframework.jdbc.core.JdbcOperations).queryForMap(<...$ARG...>, + ...)" + - pattern-not: "($O: org.springframework.jdbc.core.JdbcOperations).queryForMap(\"...\", + ...)" + - patterns: + - pattern: "($O: org.springframework.jdbc.core.JdbcOperations).queryForObject(<...$ARG...>, + ...)" + - pattern-not: "($O: org.springframework.jdbc.core.JdbcOperations).queryForObject(\"...\", + ...)" + - patterns: + - pattern: "($O: org.springframework.jdbc.core.JdbcOperations).queryForObject(<...$ARG...>, + ...)" + - pattern-not: "($O: org.springframework.jdbc.core.JdbcOperations).queryForObject(\"...\", + ...)" + - patterns: + - pattern: "($O: org.springframework.jdbc.core.JdbcOperations).queryForRowSet(<...$ARG...>, + ...)" + - pattern-not: "($O: org.springframework.jdbc.core.JdbcOperations).queryForRowSet(\"...\", + ...)" + - patterns: + - pattern: "($O: org.springframework.jdbc.core.JdbcOperations).queryForInt(<...$ARG...>, + ...)" + - pattern-not: "($O: org.springframework.jdbc.core.JdbcOperations).queryForInt(\"...\", + ...)" + - patterns: + - pattern: "($O: org.springframework.jdbc.core.JdbcOperations).queryForLong(<...$ARG...>, + ...)" + - pattern-not: "($O: org.springframework.jdbc.core.JdbcOperations).queryForLong(\"...\", + ...)" + - patterns: + - pattern: "($O: org.springframework.jdbc.core.JdbcOperations).update(<...$ARG...>, + ...)" + - pattern-not: "($O: org.springframework.jdbc.core.JdbcOperations).update(\"...\", + ...)" + - patterns: + - pattern: "($O: org.springframework.jdbc.core.JdbcTemplate).batchUpdate(<...$ARG...>, + ...)" + - pattern-not: "($O: org.springframework.jdbc.core.JdbcTemplate).batchUpdate(\"...\", + ...)" + - patterns: + - pattern: "($O: org.springframework.jdbc.core.JdbcTemplate).execute(<...$ARG...>, + ...)" + - pattern-not: "($O: org.springframework.jdbc.core.JdbcTemplate).execute(\"...\", + ...)" + - patterns: + - pattern: "($O: org.springframework.jdbc.core.JdbcTemplate).query(<...$ARG...>, + ...)" + - pattern-not: "($O: org.springframework.jdbc.core.JdbcTemplate).query(\"...\", + ...)" + - patterns: + - pattern: "($O: org.springframework.jdbc.core.JdbcTemplate).queryForList(<...$ARG...>, + ...)" + - pattern-not: "($O: org.springframework.jdbc.core.JdbcTemplate).queryForList(\"...\", + ...)" + - patterns: + - pattern: "($O: org.springframework.jdbc.core.JdbcTemplate).queryForMap(<...$ARG...>, + ...)" + - pattern-not: "($O: org.springframework.jdbc.core.JdbcTemplate).queryForMap(\"...\", + ...)" + - patterns: + - pattern: "($O: org.springframework.jdbc.core.JdbcTemplate).queryForObject(<...$ARG...>, + ...)" + - pattern-not: "($O: org.springframework.jdbc.core.JdbcTemplate).queryForObject(\"...\", + ...)" + - patterns: + - pattern: "($O: org.springframework.jdbc.core.JdbcTemplate).queryForRowSet(<...$ARG...>, + ...)" + - pattern-not: "($O: org.springframework.jdbc.core.JdbcTemplate).queryForRowSet(\"...\", + ...)" + - patterns: + - pattern: "($O: org.springframework.jdbc.core.JdbcTemplate).queryForInt(<...$ARG...>, + ...)" + - pattern-not: "($O: org.springframework.jdbc.core.JdbcTemplate).queryForInt(\"...\", + ...)" + - patterns: + - pattern: "($O: org.springframework.jdbc.core.JdbcTemplate).queryForLong(<...$ARG...>, + ...)" + - pattern-not: "($O: org.springframework.jdbc.core.JdbcTemplate).queryForLong(\"...\", + ...)" + - patterns: + - pattern: "($O: org.springframework.jdbc.core.JdbcTemplate).update(<...$ARG...>, + ...)" + - pattern-not: "($O: org.springframework.jdbc.core.JdbcTemplate).update(\"...\", + ...)" + - patterns: + - pattern: "($O: io.vertx.sqlclient.SqlClient).query(<...$ARG...>, ...)" + - pattern-not: "($O: io.vertx.sqlclient.SqlClient).query(\"...\", ...)" + - patterns: + - pattern: "($O: io.vertx.sqlclient.SqlClient).preparedQuery(<...$ARG...>, ...)" + - pattern-not: "($O: io.vertx.sqlclient.SqlClient).preparedQuery(\"...\", ...)" + - patterns: + - pattern: "($O: io.vertx.sqlclient.SqlConnection).prepare(<...$ARG...>, ...)" + - pattern-not: "($O: io.vertx.sqlclient.SqlConnection).prepare(\"...\", ...)" + - patterns: + - pattern: "($O: org.apache.turbine.om.peer.BasePeer).executeQuery(<...$ARG...>, + ...)" + - pattern-not: "($O: org.apache.turbine.om.peer.BasePeer).executeQuery(\"...\", + ...)" + - patterns: + - pattern: "($O: org.apache.torque.util.BasePeer).executeQuery(<...$ARG...>, + ...)" + - pattern-not: "($O: org.apache.torque.util.BasePeer).executeQuery(\"...\", + ...)" + - patterns: + - pattern: "($O: javax.persistence.EntityManager).createQuery(<...$ARG...>, + ...)" + - pattern-not: "($O: javax.persistence.EntityManager).createQuery(\"...\", ...)" + - patterns: + - pattern: "($O: javax.persistence.EntityManager).createNativeQuery(<...$ARG...>, + ...)" + - pattern-not: "($O: javax.persistence.EntityManager).createNativeQuery(\"...\", + ...)" + - patterns: + - pattern: "anorm.SQL(<...$ARG...>)" + - pattern-not: "anorm.SQL(\"...\")" + - patterns: + - pattern-inside: | + import anorm._ + ... + - pattern: "SQL(<...$ARG...>)" + - pattern-not: "SQL(\"...\")" + severity: "ERROR" +- id: scala_ldap_rule-AnonymousLDAP + languages: + - "scala" + message: | + Without proper access control, executing an LDAP statement that contains a + user-controlled value can allow an attacker to abuse poorly configured LDAP + context + metadata: + category: "security" + cwe: "CWE-358" + shortDescription: "Improperly implemented security check for standard" + security-severity: "Info" + patterns: + - pattern-inside: | + import javax.naming.Context; + ... + - pattern: "$ENV.put(Context.SECURITY_AUTHENTICATION, \"none\");" + severity: "WARNING" +- id: scala_ldap_rule-EntryPoisoning + languages: + - "scala" + message: | + Without proper access control, executing an LDAP statement that contains a + user-controlled value can allow an attacker to abuse poorly configured LDAP + context + metadata: + category: "security" + cwe: "CWE-358" + shortDescription: "Improperly implemented security check for standard" + security-severity: "High" + patterns: + - pattern: "new javax.naming.directory.SearchControls($SCOPE, $CLIMIT, $TLIMIT, + $ATTR, true, $DEREF)" + severity: "ERROR" +- id: scala_password_rule-ConstantDBPassword + patterns: + - pattern: "java.sql.DriverManager.getConnection($URI, $USR, \"...\");" + message: | + A potential hard-coded password was identified in a database connection string. + Passwords should not be stored directly in code + but loaded from secure locations such as a Key Management System (KMS). + + The purpose of using a Key Management System is so access can be audited and keys easily + rotated + in the event of a breach. By hardcoding passwords, it will be extremely difficult to determine + when or if, a key is compromised. + + The recommendation on which KMS to use depends on the environment the application is running + in: + + - For Google Cloud Platform consider [Cloud Key Management](https://cloud.google.com/kms/docs) + - For Amazon Web Services consider [AWS Key Management](https://aws.amazon.com/kms/) + - For on premise or other alternatives to cloud providers, consider [Hashicorp's + Vault](https://www.vaultproject.io/) + - For other cloud providers, please see their documentation + metadata: + category: "security" + cwe: "CWE-259" + shortDescription: "Use of Hard-coded Password" + technology: + - "scala" + security-severity: "Critical" + severity: "ERROR" + languages: + - "scala" +- id: scala_password_rule-EmptyDBPassword + patterns: + - pattern: "java.sql.DriverManager.getConnection($URI, $USR, \"\");" + message: | + The application does not provide authentication when communicating a database + server. It is strongly recommended that the database server be configured with + authentication and restrict what queries users can execute. + + Please see your database server's documentation on how to configure a password. + + Additionally, passwords should not be stored directly in code + but loaded from secure locations such as a Key Management System (KMS). + + The purpose of using a Key Management System is so access can be audited and keys easily + rotated + in the event of a breach. By hardcoding passwords, it will be extremely difficult to determine + when or if, a key is compromised. + + The recommendation on which KMS to use depends on the environment the application is running + in: + + - For Google Cloud Platform consider [Cloud Key Management](https://cloud.google.com/kms/docs) + - For Amazon Web Services consider [AWS Key Management](https://aws.amazon.com/kms/) + - For on premise or other alternatives to cloud providers, consider [Hashicorp's + Vault](https://www.vaultproject.io/) + - For other cloud providers, please see their documentation + metadata: + category: "security" + cwe: "CWE-259" + shortDescription: "Use of Hard-coded Password" + technology: + - "scala" + security-severity: "Critical" + languages: + - "scala" + severity: "ERROR" +- id: scala_password_rule-HardcodePassword + languages: + - "scala" + message: | + A potential hard-coded password was identified in the source code. + Passwords should not be stored directly in code + but loaded from secure locations such as a Key Management System (KMS). + + The purpose of using a Key Management System is so access can be audited and keys easily + rotated + in the event of a breach. By hardcoding passwords, it will be extremely difficult to determine + when or if, a key is compromised. + + The recommendation on which KMS to use depends on the environment the application is running + in: + + - For Google Cloud Platform consider [Cloud Key Management](https://cloud.google.com/kms/docs) + - For Amazon Web Services consider [AWS Key Management](https://aws.amazon.com/kms/) + - For on premise or other alternatives to cloud providers, consider [Hashicorp's + Vault](https://www.vaultproject.io/) + - For other cloud providers, please see their documentation + metadata: + category: "security" + cwe: "CWE-259" + shortDescription: "Use of Hard-coded Password" + technology: + - "scala" + security-severity: "High" + pattern-either: + - pattern: "java.security.KeyStore.PasswordProtection(\"...\".toCharArray())" + - pattern: "java.security.KeyStore.getInstance(...).load(..., \"...\".toCharArray())" + - pattern: "($KS: java.security.KeyStore).load(..., \"...\".toCharArray())" + - pattern: "KeyManagerFactory.getInstance(...).init(..., \"...\".toCharArray())" + - pattern: "($KMF: KeyManagerFactory).init(..., \"...\".toCharArray())" + - pattern: "PBEKeySpec(\"...\", ...)" + - pattern: "PasswordAuthentication(\"...\", \"...\")" + - pattern: "($CB: PasswordCallback).setPassword(\"...\")" + - pattern: "KerberosKey(...,\"...\",...)" + - pattern: "java.sql.DriverManager.getConnection(..., \"...\")" + - pattern: "io.vertx.ext.web.handler.CSRFHandler.create(..., \"...\")" + - pattern: "$S.setPassword(\"...\")" + severity: "ERROR" +- id: scala_perm_rule-DangerousPermissions + pattern-either: + - pattern: | + $RUNVAR = new RuntimePermission("createClassLoader"); + ... + ($PC: PermissionCollection).add($RUNVAR); + - pattern: | + $REFVAR = new ReflectPermission("suppressAccessChecks"); + ... + ($PC: PermissionCollection).add($REFVAR); + - pattern: "($PC: PermissionCollection).add(new ReflectPermission (\"suppressAccessChecks\"))" + - pattern: "($PC: PermissionCollection).add(new RuntimePermission(\"createClassLoader\"))" + languages: + - "scala" + message: | + Do not grant dangerous combinations of permissions. + metadata: + shortDescription: "Insecure inherited permissions" + category: "security" + cwe: "CWE-277" + confidence: "HIGH" + security-severity: "Info" + severity: "WARNING" +- id: scala_perm_rule-OverlyPermissiveFilePermissionInline + languages: + - "scala" + message: | + Overly permissive file permission + metadata: + category: "security" + confidence: "HIGH" + cwe: "CWE-732" + shortDescription: "Incorrect Permission Assignment for Critical Resource" + security-severity: "High" + patterns: + - pattern-either: + - pattern: "java.nio.file.Files.setPosixFilePermissions(..., java.nio.file.attribute.PosixFilePermissions.fromString(\"$PERM_STRING\"));" + - pattern: | + $PERMISSIONS = java.nio.file.attribute.PosixFilePermissions.fromString("$PERM_STRING"); + ... + java.nio.file.Files.setPosixFilePermissions(..., $PERMISSIONS); + - metavariable-regex: + metavariable: "$PERM_STRING" + regex: "[rwx-]{6}[rwx]{1,}" + severity: "WARNING" +- id: scala_perm_rule-OverlyPermissiveFilePermissionObj + languages: + - "scala" + message: | + Overly permissive file permission + metadata: + category: "security" + confidence: "HIGH" + cwe: "CWE-732" + shortDescription: "Incorrect Permission Assignment for Critical Resource" + security-severity: "Medium" + patterns: + - pattern-inside: | + ... + java.nio.file.Files.setPosixFilePermissions(..., $PERMS); + - pattern-either: + - pattern: "$PERMS.add($P);" + - pattern: "$A = $B + $P;" + - metavariable-regex: + metavariable: "$P" + regex: "(PosixFilePermission.){0,1}(OTHERS_)" + severity: "WARNING" +- id: scala_script_rule-ScriptInjection + languages: + - "scala" + message: | + The software constructs all or part of a code segment using externally-influenced + input from an upstream component, but it does not neutralize or incorrectly + neutralizes special elements that could modify the syntax or behavior of the + intended code segment. + metadata: + cwe: "CWE-94" + shortDescription: "Improper Control of Generation of Code ('Code Injection')" + security-severity: "Info" + category: "security" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + patterns: + - pattern: "($ENGINE: javax.script.ScriptEngine).eval($ARG)" + - pattern-not: "($ENGINE: javax.script.ScriptEngine).eval(\"...\")" + severity: "ERROR" +- id: scala_script_rule-SpelView + languages: + - "scala" + message: | + The software constructs all or part of a code segment using externally-influenced + input from an upstream component, but it does not neutralize or incorrectly + neutralizes special elements that could modify the syntax or behavior of the + intended code segment. + metadata: + cwe: "CWE-94" + shortDescription: "Improper Control of Generation of Code ('Code Injection')" + security-severity: "Medium" + category: "security" + owasp: + - "A1:2017-Injection" + - "A03:2021-Injection" + patterns: + - pattern: "($P: org.springframework.expression.spel.standard.SpelExpressionParser).parseExpression($ARG);" + - pattern-not: "($P: org.springframework.expression.spel.standard.SpelExpressionParser + ).parseExpression(\"...\");" + severity: "ERROR" +- id: scala_smtp_rule-InsecureSmtp + languages: + - "scala" + message: | + Server identity verification is disabled when making SSL connections. + metadata: + cwe: "CWE-297" + shortDescription: "Improper Validation of Certificate with Host Mismatch" + security-severity: "High" + category: "security" + owasp: + - "A2:2017-Broken Authentication" + - "A07:2021-Identification and Authentication Failures" + patterns: + - pattern-either: + - pattern-inside: | + $E = new org.apache.commons.mail.SimpleEmail(...); + ... + - pattern-inside: | + $E = new org.apache.commons.mail.Email(...); + ... + - pattern-inside: | + $E = new org.apache.commons.mail.MultiPartEmail(...); + ... + - pattern-inside: | + $E = new org.apache.commons.mail.HtmlEmail(...); + ... + - pattern-inside: | + $E = new org.apache.commons.mail.ImageHtmlEmail(...); + ... + - pattern-not: | + $E.setSSLOnConnect(true); + ... + $E.setSSLCheckServerIdentity(true); + severity: "ERROR" +- id: scala_smtp_rule-SmtpClient + languages: + - "scala" + message: | + Simple Mail Transfer Protocol (SMTP) is a the text based protocol used for + email delivery. Like with HTTP, headers are separate by new line separator. If + kuser input is place in a header line, the application should remove or replace + new line characters (CR / LF). You should use a safe wrapper such as Apache + Common Email and Simple Java Mail which filter special characters that can lead + to header injection. + metadata: + category: "security" + cwe: "CWE-77" + shortDescription: "Improper Neutralization of Special Elements used in a Command" + security-severity: "High" + patterns: + - pattern-either: + - patterns: + - pattern-inside: | + $M = new MimeMessage(...); + ... + - pattern: "$M.setSubject($ARG);" + - pattern-not: "$M.setSubject(\"...\")" + - patterns: + - pattern-inside: | + $M = new MimeMessage(...); + ... + - pattern: "$M.addHeader($ARG1, $ARG2)" + - pattern-not: "$M.addHeader(\"...\", \"...\")" + - patterns: + - pattern-inside: | + $M = new MimeMessage(...); + ... + - pattern: "$M.setDescription($ARG)" + - pattern-not: "$M.setDescription(\"...\")" + - patterns: + - pattern-inside: | + $M = new MimeMessage(...); + ... + - pattern: "$M.setDisposition($ARG)" + - pattern-not: "$M.setDisposition(\"...\")" + severity: "ERROR" +- id: scala_ssrf_rule-PlaySSRF + languages: + - "scala" + message: | + Server-Side Request Forgery occur when a web server executes a request to a user supplied + destination parameter that is not validated. Such vulnerabilities could allow an attacker to + access internal services or to launch attacks from your web server. + metadata: + category: "security" + cwe: "CWE-918" + shortDescription: "Server-Side Request Forgery (SSRF)" + security-severity: "Medium" + patterns: + - pattern-not-inside: | + object $CLAZZ { + ... + $ARG = ... + ... + } + - pattern-not-inside: | + class $CLAZZ { + ... + $ARG = ... + ... + } + - pattern-either: + - patterns: + - pattern-inside: | + import play.api.libs.ws._ + ... + - pattern-not: "($W:WSClient).url(\"...\")" + - pattern-not: "($W:WSClient).url(\"...\" + \"...\")" + - pattern: "($W:WSClient).url(<...$ARG...>)" + - patterns: + - pattern: "($W:play.api.libs.ws.WSClient).url(<...$ARG...>)" + - pattern-not: "($W:play.api.libs.ws.WSClient).url(\"...\")" + - pattern-not: "($W:play.api.libs.ws.WSClient).url(\"...\" + \"...\")" + severity: "ERROR" +- id: scala_ssrf_rule-SSRF + languages: + - "scala" + message: | + Server-Side Request Forgery occur when a web server executes a request to a user supplied + destination parameter that is not validated. Such vulnerabilities could allow an attacker to + access internal services or to launch attacks from your web server. + metadata: + category: "security" + cwe: "CWE-918" + shortDescription: "Server-Side Request Forgery (SSRF)" + security-severity: "Low" + pattern-either: + - patterns: + - pattern-either: + - pattern-inside: | + import java.net._ + ... + - pattern-inside: | + import java.net.URL + ... + - pattern-inside: | + import java.net.URI + ... + - pattern: "new $TYPE(...). ... .$FUNC" + - pattern-not: "new $TYPE(\"...\"). ... .$FUNC" + - metavariable-pattern: + metavariable: "$FUNC" + pattern-either: + - pattern: "connect" + - pattern: "GetContent" + - pattern: "openConnection" + - pattern: "openStream" + - pattern: "getContent" + - metavariable-pattern: + metavariable: "$TYPE" + pattern-either: + - pattern: "URL" + - pattern: "java.net.URL" + - pattern: "URI" + - pattern: "java.net.URI" + - patterns: + - pattern-either: + - pattern-inside: | + import java.net.*; + ... + - pattern-inside: | + import java.net.InetSocketAddress; + ... + - pattern: | + new InetSocketAddress(..., $PORT) + - pattern-not: | + new InetSocketAddress("...", $PORT) + severity: "ERROR" +- id: scala_strings_rule-BadHexConversion + languages: + - "scala" + message: | + When converting a byte array containing a hash signature to a human readable string, a + conversion mistake can be made if the array is read byte by byte. + metadata: + category: "security" + confidence: "HIGH" + cwe: "CWE-704" + shortDescription: "Incorrect Type Conversion or Cast" + security-severity: "Medium" + pattern-either: + - pattern: | + $B_ARR = ($MD: java.security.MessageDigest).digest(...); + ... + for(...) { + ... + Integer.toHexString(...); + } + - pattern: | + $B_ARR = ($MD: java.security.MessageDigest).digest(...); + ... + while(...) { + ... + Integer.toHexString(...); + } + severity: "WARNING" +- id: scala_strings_rule-FormatStringManipulation + languages: + - "scala" + message: | + Allowing user input to control format parameters could enable an attacker to cause exceptions + to be thrown or leak information.Attackers may be able to modify the format string argument, + such that an exception is thrown. If this exception is left uncaught, it may crash the + application. Alternatively, if sensitive information is used within the unused arguments, + attackers may change the format string to reveal this information. + metadata: + category: "security" + confidence: "HIGH" + cwe: "CWE-134" + shortDescription: "Use of Externally-Controlled Format String" + security-severity: "Info" + patterns: + - pattern-either: + - patterns: + - pattern-inside: | + $INPUT = ($REQ: javax.servlet.http.HttpServletRequest).getParameter(...); + ... + - pattern-inside: | + $FORMAT_STR = <... $INPUT ...>; + - patterns: + - pattern-inside: | + val $INPUT = ($REQ: javax.servlet.http.HttpServletRequest).getParameter(...); + ... + - pattern-inside: | + val $FORMAT_STR = <... $INPUT ...>; + ... + - pattern-inside: | + val $FORMAT_STR = ... + ($REQ: javax.servlet.http.HttpServletRequest).getParameter(...) + ...; ... + - pattern-inside: | + val $FORMAT_STR = ... + ($REQ: javax.servlet.http.HttpServletRequest).getParameter(...); ... + - pattern-either: + - pattern: "$VAL = <... $INPUT ...>" + - pattern: "String.format($FORMAT_STR, ...);" + - pattern: "String.format(java.util.Locale.$LOCALE, $FORMAT_STR, ...);" + - pattern: "($F: java.util.Formatter).format($FORMAT_STR, ...);" + - pattern: "($F: java.util.Formatter).format(java.util.Locale.$LOCALE, $FORMAT_STR, + ...);" + - pattern: "($F: java.io.PrintStream).printf($FORMAT_STR, ...);" + - pattern: "($F: java.io.PrintStream).printf(java.util.Locale.$LOCALE, $FORMAT_STR, + ...);" + - pattern: "($F: java.io.PrintStream).format($FORMAT_STR, ...);" + - pattern: "($F: java.io.PrintStream).format(java.util.Locale.$LOCALE, $FORMAT_STR, + ...);" + - pattern: "System.out.printf($FORMAT_STR, ...);" + - pattern: "System.out.printf(java.util.Locale.$LOCALE, $FORMAT_STR, ...);" + - pattern: "System.out.format($FORMAT_STR, ...);" + - pattern: "System.out.format(java.util.Locale.$LOCALE, $FORMAT_STR, ...);" + severity: "ERROR" +- id: scala_strings_rule-ImproperUnicode + languages: + - "scala" + message: | + Improper Handling of Unicode Encoding + metadata: + category: "security" + confidence: "HIGH" + cwe: "CWE-176" + shortDescription: "Improper Handling of Unicode Encoding" + security-severity: "Medium" + pattern-either: + - patterns: + - pattern-either: + - pattern: | + $S = ($INPUT: String).$TRANSFORM(...); + ... + $S.$METHOD(...); + - pattern: "($INPUT: String).$TRANSFORM().$METHOD(...);" + - metavariable-regex: + metavariable: "$METHOD" + regex: "(equals|equalsIgnoreCase|indexOf)" + - metavariable-regex: + metavariable: "$TRANSFORM" + regex: "(toLowerCase|toUpperCase)" + - pattern: "java.text.Normalizer.normalize(...);" + - pattern: "java.net.IDN.toASCII(...);" + - pattern: "($U: URI).toASCIIString()" + severity: "ERROR" +- id: scala_strings_rule-ModifyAfterValidation + patterns: + - pattern: | + $Y.matcher($VAR); + ... + $VAR.$METHOD(...); + - metavariable-regex: + metavariable: "$METHOD" + regex: "(replace)" + languages: + - "scala" + message: | + CERT: IDS11-J. Perform any string modifications before validation + metadata: + shortDescription: "Collapse of data into unsafe value" + category: "security" + cwe: "CWE-182" + confidence: "HIGH" + security-severity: "Info" + severity: "WARNING" +- id: scala_strings_rule-NormalizeAfterValidation + patterns: + - pattern: | + $Y = java.util.regex.Pattern.compile("[<>]"); + ... + $Y.matcher($VAR); + ... + java.text.Normalizer.normalize($VAR, ...); + languages: + - "scala" + message: | + IDS01-J. Normalize strings before validating them + metadata: + shortDescription: "Collapse of data into unsafe value" + category: "security" + cwe: "CWE-182" + confidence: "HIGH" + security-severity: "Info" + severity: "WARNING" +- id: scala_templateinjection_rule-TemplateInjection + languages: + - "scala" + message: | + A malicious user in control of a template can run malicious code on the + server-side. Velocity templates should be seen as scripts. + metadata: + category: "security" + cwe: "CWE-94" + shortDescription: "Improper Control of Generation of Code ('Code Injection')" + security-severity: "Info" + pattern-either: + - patterns: + - pattern: "org.apache.velocity.app.Velocity.evaluate(..., $VAR)" + - pattern-not: "org.apache.velocity.app.Velocity.evaluate(..., \"...\")" + - patterns: + - pattern-not-inside: | + $C = ($CFG: freemarker.template.Configuration).getTemplate("..."); + ... + - pattern-inside: | + $C = ($CFG: freemarker.template.Configuration).getTemplate($IN); + ... + - pattern: "$C.process(...)" + - patterns: + - pattern-inside: | + import com.mitchellbosecke.pebble.PebbleEngine; + ... + - pattern-inside: | + $C = $T.getTemplate($IN); + ... + - pattern-not-inside: | + $C = $T.getTemplate("..."); + ... + - pattern: "$C.evaluate(...)" + severity: "ERROR" +- id: scala_unsafe_rule-ExternalConfigControl + languages: + - "scala" + message: | + Allowing external control of system settings can disrupt service or cause an application to + behave in unexpected, and potentially malicious ways. An attacker could cause an error by + providing a nonexistent catalog name or connect to an unauthorized portion of the database. + metadata: + category: "security" + cwe: "CWE-15" + shortDescription: "External Control of System or Configuration Setting" + technology: + - "scala" + security-severity: "High" + patterns: + - pattern: | + $TAINTED = ($REQ: HttpServletRequest).getParameter(...); + ... + ($CONN: java.sql.Connection).setCatalog($TAINTED); + severity: "WARNING" +- id: scala_unsafe_rule-InformationExposure + languages: + - "scala" + message: | + The sensitive information may be valuable information on its own (such as a password), or it + may be useful for launching other, more deadly attacks. If an attack fails, an attacker may use + error information provided by the server to launch another more focused attack. For example, an + attempt to exploit a path traversal weakness (CWE-22) might yield the full pathname of the + installed application. + metadata: + category: "security" + cwe: "CWE-209" + shortDescription: "Information Exposure Through an Error Message" + technology: + - "scala" + security-severity: "Low" + patterns: + - pattern: "$E.printStackTrace(...)" + severity: "WARNING" +- id: scala_unsafe_rule-SensitiveDataExposure + languages: + - "scala" + message: | + Applications can unintentionally leak information about their configuration, internal + workings, or violate privacy through a variety of application problems. Pages that provide + different responses based on the validity of the data can lead to Information Leakage; + specifically when data deemed confidential is being revealed as a result of the web + application's design. + metadata: + category: "security" + cwe: "CWE-497" + shortDescription: "Exposure of sensitive system information to an unauthorized control sphere" + technology: + - "scala" + - "play" + security-severity: "Info" + patterns: + - pattern-inside: | + def $FUNC(..., $ARG: String, ...) = $TYPE { + ... + } + - pattern-inside: | + $VAL = ($C: play.api.Configuration).underlying.getString($ARG) + ... + - pattern: "Ok(<...$VAL...>)" + severity: "WARNING" +- id: scala_xml_rule-ApacheXmlRpc + languages: + - "scala" + message: | + Enabling extensions in Apache XML RPC server or client can lead to deserialization + vulnerability which would allow an attacker to execute arbitrary code. + metadata: + category: "security" + cwe: "CWE-502" + shortDescription: "Deserialization of Untrusted Data" + security-severity: "Info" + patterns: + - pattern-either: + - patterns: + - pattern-inside: | + val $VAR = new XmlRpcServerConfigImpl(); + ... + - pattern: "$VAR.setEnabledForExtensions(true);" + - patterns: + - pattern-inside: | + val $VAR = new org.apache.xmlrpc.client.XmlRpcClientConfigImpl(); + ... + - pattern: "$VAR.setEnabledForExtensions(true);" + severity: "WARNING" +- id: scala_xml_rule-SAMLIgnoreComments + languages: + - "scala" + message: | + Ignoring XML comments in SAML may lead to authentication bypass + metadata: + category: "security" + shortDescription: "Weak authentication" + cwe: "CWE-1390" + security-severity: "Medium" + pattern: "($POOL: BasicParserPool).setIgnoreComments(false);" + severity: "WARNING" +- id: scala_xml_rule-XmlDecoder + languages: + - "scala" + message: | + Avoid using XMLDecoder to parse content from an untrusted source. + metadata: + category: "security" + cwe: "CWE-502" + shortDescription: "Deserialization of Untrusted Data" + security-severity: "High" + patterns: + - pattern-inside: | + $D = new java.beans.XMLDecoder($IN); + ... + - pattern-not-inside: | + $DX = new java.beans.XMLDecoder("..."); + ... + - pattern: "$D.readObject" + severity: "WARNING" +- id: scala_xml_rule-XsltTransform + mode: "taint" + pattern-sources: + - patterns: + - pattern-either: + - patterns: + - pattern-inside: | + $FUNC(...,String $VAR, ...) { + ... + } + - pattern-either: + - pattern: "new FileInputStream(<... $VAR ...>);" + - pattern: "getClass.getResourceAsStream(<... $VAR ...>)" + - patterns: + - pattern-inside: | + class $CLZ { + String $X = "..."; + ... + } + - pattern-inside: | + $FUNC(...,String $Y, ...) { + ... + } + - pattern-either: + - pattern: "new FileInputStream($X + $Y);" + - pattern: "getClass.getResourceAsStream($X + $Y)" + pattern-sinks: + - patterns: + - pattern-either: + - pattern-inside: |- + (javax.xml.transform.TransformerFactory $T).newTransformer($SRC, ...) + - pattern-inside: |- + (javax.xml.transform.Transformer $T).transform($SRC, ...) + - pattern: "$SRC" + languages: + - "java" + message: | + It is possible to attach malicious behavior to those style sheets. Therefore, if an attacker + can control the content or the source of the style sheet, he might be able to trigger remote + code execution. + metadata: + shortDescription: "XML injection (aka Blind XPath injection)" + category: "security" + cwe: "CWE-91" + security-severity: "Medium" + severity: "WARNING" +- id: scala_xpathi_rule-XpathInjection + languages: + - "scala" + message: | + The input values included in SQL queries need to be passed in safely. Bind + variables in prepared statements can be used to easily mitigate the risk of + SQL injection. + metadata: + category: "security" + cwe: "CWE-611" + shortDescription: "Improper Restriction of XML External Entity Reference ('XXE')" + security-severity: "Medium" + mode: "taint" + pattern-sinks: + - patterns: + - pattern-either: + - pattern-inside: |- + import javax.xml.xpath._ + ... + - pattern-inside: |- + import javax.xml.xpath.XPath + ... + - pattern-either: + - pattern: "$Y.compile(...)" + - pattern: "$X.evaluate(..., $ARG2)" + pattern-sources: + - patterns: + - pattern-inside: | + def $FUNC(..., $ARG: $TYPE,...): $RET = { + ... + } + - pattern: "$ARG" + severity: "ERROR" +- id: scala_xss_rule-MVCApi + languages: + - "scala" + message: | + Disabling HTML escaping put the application at risk for Cross-Site Scripting (XSS). + metadata: + category: "security" + cwe: "CWE-79" + shortDescription: "Improper Neutralization of Input During Web Page Generation + ('Cross-site Scripting')" + security-severity: "Info" + mode: "taint" + pattern-sanitizers: + - pattern: "org.owasp.encoder.Encode.forHtml(...)" + pattern-sinks: + - pattern: "Ok(...)" + pattern-sources: + - patterns: + - pattern-inside: | + def $FUNC(..., $ARG: String, ...) = Action { + ... + } + - focus-metavariable: "$ARG" + severity: "WARNING" +- id: scala_xss_rule-RequestWrapper + languages: + - "scala" + message: | + Avoid using custom XSS filtering. Please use standard sanitization functions. + metadata: + category: "security" + cwe: "CWE-79" + shortDescription: "Improper Neutralization of Input During Web Page Generation + ('Cross-site Scripting')" + security-severity: "Medium" + patterns: + - pattern-inside: | + class $CLASS(...) extends HttpServletRequestWrapper(...) { + ... + } + - pattern: "def stripXSS(...) = { ... }" + severity: "INFO" +- id: scala_xss_rule-WicketXSS + languages: + - "scala" + message: | + Disabling HTML escaping put the application at risk for Cross-Site Scripting (XSS). + metadata: + category: "security" + cwe: "CWE-79" + shortDescription: "Improper Neutralization of Input During Web Page Generation + ('Cross-site Scripting')" + security-severity: "Medium" + patterns: + - pattern: "($X: Label).setEscapeModelStrings(false);" + severity: "WARNING" +- id: scala_xss_rule-XSSReqParamToServletWriter + languages: + - "scala" + message: | + Servlet reflected cross site scripting vulnerability + metadata: + category: "security" + cwe: "CWE-79" + shortDescription: "Improper Neutralization of Input During Web Page Generation" + technology: + - "scala" + security-severity: "Medium" + mode: "taint" + pattern-sanitizers: + - pattern: "Encode.forHtml(...)" + - pattern: "org.owasp.esapi.Encoder.encodeForSQL(...)" + pattern-sinks: + - patterns: + - pattern-inside: |- + def $FUNC(..., $RES: HttpServletResponse, ...): $TYPE = {...} + - pattern-inside: | + $WRITER = $RES.getWriter + ... + - pattern: "$WRITER.write(...)" + - patterns: + - pattern-inside: |- + def $FUNC(..., $RES: HttpServletResponse, ...): $TYPE = {...} + - pattern: "$RES.getWriter.write(...)" + - patterns: + - pattern-inside: |- + def $FUNC(..., $RES: HttpServletResponse, ...): $TYPE = {...} + - pattern: "$RES.getWriter.print(...)" + pattern-sources: + - patterns: + - pattern-inside: |- + def $FUNC(..., $REQ: HttpServletRequest, ...): $TYPE = {...} + - pattern-either: + - pattern: "$REQ.getParameter(...)" + - pattern: "$REQ.getQueryString" + severity: "WARNING" +- id: scala_xss_rule-XSSServlet + languages: + - "scala" + message: | + A potential XSS was found. It could be used to execute unwanted JavaScript in a + client's browser. + metadata: + category: "security" + cwe: "CWE-79" + shortDescription: "Improper Neutralization of Input During Web Page Generation + ('Cross-site Scripting')" + security-severity: "Info" + mode: "taint" + pattern-sanitizers: + - patterns: + - pattern-inside: |- + org.owasp.encoder.Encode.forHtml($TAINTED); + - pattern: "$TAINTED" + pattern-sinks: + - patterns: + - pattern-inside: |- + def $FUNC(..., $RES: HttpServletResponse, ...): $TYPE = {...} + - pattern-inside: | + $WRITER = $RES.getWriter; + ... + - pattern: "$WRITER.write($DATA,...);" + - pattern: "$DATA" + - patterns: + - pattern-inside: |- + def $FUNC(..., $RES: HttpServletResponse, ...): $TYPE = {...} + - pattern: "$RES.getWriter.write($DATA,...);" + - pattern: "$DATA" + pattern-sources: + - patterns: + - pattern-inside: |- + def $FUNC(..., $REQ: HttpServletRequest, ...): $TYPE = {...} + - pattern: "$REQ.getParameter(...);" + severity: "WARNING" +- id: scala_xxe_rule-Document + languages: + - "scala" + message: | + XML External Entity (XXE) attacks can occur when an XML parser supports XML + entities while processing XML received from an untrusted source. + metadata: + category: "security" + cwe: "CWE-611" + shortDescription: "Improper Restriction of XML External Entity Reference ('XXE')" + security-severity: "Medium" + patterns: + - pattern-inside: | + $DF = DocumentBuilderFactory.newInstance + ... + - pattern-not-inside: | + $DF.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true) + ... + - pattern-not-inside: | + $DF.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true) + ... + - pattern: "$DB.parse(...)" + severity: "ERROR" +- id: scala_xxe_rule-SaxParserXXE + languages: + - "scala" + message: | + XML External Entity (XXE) attacks can occur when an XML parser supports XML + entities while processing XML received from an untrusted source. + metadata: + category: "security" + cwe: "CWE-611" + shortDescription: "Improper Restriction of XML External Entity Reference ('XXE')" + security-severity: "Info" + patterns: + - pattern-inside: | + val $SF = SAXParserFactory.newInstance + ... + - pattern-not-inside: | + $SF.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true) + ... + - pattern-not-inside: | + $SF.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true) + ... + - pattern-inside: | + val $P = $SFP.newSAXParser + ... + - pattern: "$P.parse(...);" + severity: "ERROR" +- id: scala_xxe_rule-Trans + languages: + - "scala" + message: | + XML External Entity (XXE) attacks can occur when an XML parser supports XML + entities while processing XML received from an untrusted source. + metadata: + category: "security" + cwe: "CWE-611" + shortDescription: "Improper Restriction of XML External Entity Reference ('XXE')" + security-severity: "Medium" + mode: "taint" + pattern-sanitizers: + - pattern: "$T.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, \"\");" + - pattern: "$T.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, \"\");" + - pattern: "$T.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);" + pattern-sinks: + - pattern: "$T.transform(...)" + pattern-sources: + - patterns: + - pattern-either: + - pattern-inside: |- + import javax.xml.transform._ + ... + - pattern-inside: |- + import javax.xml.transform.Transformer + ... + - pattern: "$FACT.newTransformer" + severity: "ERROR" +- id: scala_xxe_rule-XMLRdr + languages: + - "scala" + message: | + XML External Entity (XXE) attacks can occur when an XML parser supports XML + entities while processing XML received from an untrusted source. + metadata: + category: "security" + cwe: "CWE-611" + shortDescription: "Improper Restriction of XML External Entity Reference ('XXE')" + security-severity: "Medium" + patterns: + - pattern-inside: | + val $R = XMLReaderFactory.createXMLReader + ... + - pattern-not-inside: | + $R.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true) + ... + - pattern: "$R.parse(...)" + severity: "ERROR" +- id: scala_xxe_rule-XMLStreamRdr + languages: + - "scala" + message: | + XML External Entity (XXE) attacks can occur when an XML parser supports XML + entities while processing XML received from an untrusted source. + metadata: + category: "security" + cwe: "CWE-611" + shortDescription: "Improper Restriction of XML External Entity Reference ('XXE')" + security-severity: "Medium" + patterns: + - pattern-inside: | + $SF = XMLInputFactory.newFactory + ... + - pattern-not-inside: | + $SF.setProperty(XMLInputFactory.SUPPORT_DTD, false) + ... + - pattern-not-inside: | + $SF.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, false) + ... + - pattern: "$SF.createXMLStreamReader(...)" + severity: "ERROR" +- id: scala_xxe_rule-XPathXXE + languages: + - "scala" + message: | + XML External Entity (XXE) attacks can occur when an XML parser supports XML + entities while processing XML received from an untrusted source. + metadata: + category: "security" + cwe: "CWE-611" + shortDescription: "Improper Restriction of XML External Entity Reference ('XXE')" + security-severity: "Medium" + patterns: + - pattern-inside: | + val $DF = DocumentBuilderFactory.newInstance + ... + - pattern-not-inside: | + $DF.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "") + ... + - pattern-not-inside: | + $DF.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "") + ... + - pattern-not-inside: | + $DF.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true) + ... + - pattern-not-inside: | + $DF.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true) + ... + - pattern-inside: | + $B = $DF.newDocumentBuilder + ... + - pattern: "$XPATH.evaluate(...)" + severity: "ERROR" +- id: codacy.java.security.hard-coded-password + severity: ERROR + languages: + - java + patterns: + - pattern-either: + - pattern: String $PASSWORD = "$VALUE"; + - metavariable-regex: + metavariable: "$PASSWORD" + regex: "(?i).*(password|motdepasse|heslo|adgangskode|wachtwoord|salasana|passwort|passord|senha|geslo|clave|losenord|clave|parola|secret|pwd).*" + message: Hardcoded passwords are a security risk. They can be easily found by attackers and used to gain unauthorized access to the system. + metadata: + owasp: + - A3:2017 Sensitive Data Exposure + description: Hardcoded passwords are a security risk. + category: security + technology: + - java + impact: HIGH + confidence: MEDIUM +- id: codacy.csharp.security.hard-coded-password + severity: ERROR + languages: + - csharp + patterns: + - pattern-either: + - pattern: var $PASSWORD = "$VALUE"; + - metavariable-regex: + metavariable: "$PASSWORD" + regex: "(?i).*(password|motdepasse|heslo|adgangskode|wachtwoord|salasana|passwort|passord|senha|geslo|clave|losenord|clave|parola|secret|pwd).*" + message: Hardcoded passwords are a security risk. They can be easily found by attackers and used to gain unauthorized access to the system. + metadata: + owasp: + - A3:2017 Sensitive Data Exposure + description: Hardcoded passwords are a security risk. + category: security + technology: + - .net + impact: HIGH + confidence: MEDIUM +- id: codacy.javascript.security.hard-coded-password + severity: ERROR + languages: + - javascript + - typescript + patterns: + - pattern-either: + - pattern: let $PASSWORD = "$VALUE" + - pattern: const $PASSWORD = "$VALUE" + - pattern: var $PASSWORD = "$VALUE" + - pattern: let $PASSWORD = '$VALUE' + - pattern: const $PASSWORD = '$VALUE' + - pattern: var $PASSWORD = '$VALUE' + - pattern: let $PASSWORD = `$VALUE` + - pattern: const $PASSWORD = `$VALUE` + - pattern: var $PASSWORD = `$VALUE` + - metavariable-regex: + metavariable: "$PASSWORD" + regex: "(?i).*(password|motdepasse|heslo|adgangskode|wachtwoord|salasana|passwort|passord|senha|geslo|clave|losenord|clave|parola|secret|pwd).*" + message: Hardcoded passwords are a security risk. They can be easily found by attackers and used to gain unauthorized access to the system. + metadata: + owasp: + - A3:2017 Sensitive Data Exposure + description: Hardcoded passwords are a security risk. + category: security + technology: + - javascript + impact: HIGH + confidence: MEDIUM +- id: codacy.generic.plsql.empty-strings + severity: WARNING + languages: + - generic + pattern: $VAR VARCHAR2($LENGTH) := ''; + message: Empty strings can lead to unexpected behavior and should be handled carefully. + metadata: + description: Detects empty strings in the code which might cause issues or bugs. + category: security + impact: MEDIUM + confidence: MEDIUM +- id: codacy.generic.plsql.find-all-passwords + severity: ERROR + languages: + - generic + pattern: | + $PASSWORD VARCHAR2($LENGTH) := $...VALUE; + options: + generic_ellipsis_max_span: 0 + message: > + Hardcoded or exposed passwords are a security risk. They can be easily found by attackers and used to gain unauthorized access to the system. + metadata: + owasp: + - A3:2017 Sensitive Data Exposure + description: Finding all occurrences of passwords in different languages and formats, while avoiding common false positives. + category: security + impact: HIGH + confidence: MEDIUM +- id: codacy.generic.plsql.resource-injection + severity: ERROR + languages: + - generic + patterns: + - pattern-either: + - pattern: | + $RESOURCE := DBMS_CUBE.BUILD($...ARGS); + - pattern: | + $RESOURCE := DBMS_FILE_TRANSFER.COPY_FILE($...ARGS); + - pattern: | + $RESOURCE := DBMS_FILE_TRANSFER.GET_FILE($...ARGS); + - pattern: | + $RESOURCE := DBMS_FILE_TRANSFER.PUT_FILE($...ARGS); + - pattern: | + $RESOURCE := DBMS_SCHEDULER.GET_FILE($...ARGS); + - pattern: | + $RESOURCE := DBMS_SCHEDULER.PUT_FILE($...ARGS); + - pattern: | + $RESOURCE := DBMS_SCHEDULER.CREATE_PROGRAM($...ARGS); + - pattern: | + $RESOURCE := DBMS_SERVICE.CREATE_SERVICE($...ARGS); + - pattern: | + $RESOURCE := UTL_TCP.OPEN_CONNECTION($...ARGS); + - pattern: | + $RESOURCE := UTL_SMTP.OPEN_CONNECTION($...ARGS); + - pattern: | + $RESOURCE := WPG_DOCLOAD.DOWNLOAD_FILE($...ARGS); + options: + generic_ellipsis_max_span: 0 + message: Resource injection detected. This can lead to unauthorized access or manipulation of resources. + metadata: + owasp: + - A3:2017 Sensitive Data Exposure + description: Detects assignments in PL/SQL involving risky DBMS functions that might cause security issues. + category: security + impact: HIGH + confidence: MEDIUM +- id: codacy.generic.sql.grant-all + severity: ERROR + languages: + - generic + pattern: | + GRANT ALL $X + paths: + include: + - '*.sql' + message: > + GRANT ALL privileges should not be used as it gives excessive permissions that violate the principle of least privilege. + Instead, grant only the specific privileges that are required. + metadata: + owasp: + - A5:2017 Broken Access Control + description: Detects use of GRANT ALL which gives excessive database privileges + category: security + impact: HIGH + confidence: LOW +- id: codacy.generic.sql.grant-select-no-role + languages: + - generic + severity: ERROR + message: > + GRANT SELECT privileges should only be given to role-based accounts + (ending in '_role'). Direct grants to users or non-role accounts violate + security best practices. + pattern-regex: GRANT\s+(DELETE|INSERT|SELECT|UPDATE)(\s*,\s*(DELETE|INSERT|SELECT|UPDATE))*\s+ON\s+[a-zA-Z0-9_]+(\.[a-zA-Z0-9_*]+)?\s+TO\s+(?![a-zA-Z0-9_]*_role\b)[a-zA-Z0-9_]+ + paths: + include: + - "*.sql" + metadata: + owasp: + - A5:2017 Broken Access Control + description: Detects GRANT SELECT statements that are not targeting role-based + accounts + category: security + impact: MEDIUM + confidence: LOW +- id: codacy.generic.sql.fnd-profile-in-query + severity: ERROR + languages: + - generic + patterns: + - pattern-either: + - pattern-regex: (?i)SELECT\s+.*\bFND_PROFILE\.[a-zA-Z0-9_]+\( + - pattern-regex: (?i)SELECT\s+.*\bFROM\b.*\bWHERE\b.*\bFND_PROFILE\.[a-zA-Z0-9_]+\( + + paths: + include: + - '*.sql' + message: > + FND_PROFILE functions should not be used directly in SELECT or WHERE clauses. + Instead, assign the FND_PROFILE function value to a variable first and then use that variable in the query. + This improves performance and maintainability. + metadata: + description: Detects direct usage of FND_PROFILE functions in SQL queries instead of using variables + category: performance + impact: MEDIUM + confidence: LOW +- id: codacy.java.security.flexible-search-sql-injection + languages: + - java + severity: ERROR + message: "Possible SQL Injection: Avoid concatenating user input in FlexibleSearchQuery." + patterns: + - pattern-either: + - pattern: | + new FlexibleSearchQuery("SELECT " + ...) + - pattern: | + new FlexibleSearchQuery("..." + $VAR + "...") + - pattern-not: | + new FlexibleSearchQuery("SELECT ... ?param") + metadata: + category: security + technology: [sap-commerce, hybris] + confidence: LOW +- id: codacy.csharp.security.null-dereference + languages: + - csharp + severity: ERROR + message: > + Potential null dereference detected. The parameter or variable could be + null and should be validated before accessing its members. Add a null + check before dereferencing the object to prevent NullReferenceException at + runtime. + patterns: + - pattern-inside: | + $RETURNTYPE $METHOD(...,$TYPE $NULLABLE, ...) { ... } + - pattern-not-inside: | + if ($NULLABLE == null) { ... } + ... + - pattern-either: + - pattern: | + $NULLABLE.$MEMBER + - pattern: | + $FUNCTION_NAME($NULLABLE, ...); + - pattern-not: | + if ($NULLABLE == null) { return ... } + ... + metadata: + category: security + technology: + - csharp + - dotnet + confidence: LOW +- id: codacy.generic.security.detect-invisible-unicode + languages: + - yaml + - json + severity: WARNING + message: It's possible to embed malicious secret instructions to AI rules files using unicode characters that are invisible to human reviewers.This can lead to future AI-generated code that has security vulnerabilities or other weaknesses baked in which may not be noticed. + pattern-regex: "[\u200B\u200C\u200D\u2060\uFEFF]" + paths: + include: + - "*.json" + - "*.yaml" + - "*.yml" + metadata: + description: Detects the invisible unicode characters + category: security + technology: + - AI + - Copilot + - Cursor + confidence: MEDIUM +- id: codacy.generic.csharp-lowercase-variables + languages: + - csharp + severity: INFO + message: "Variable names should be lowercase" + pattern-regex: (?:int|string|long|float|char|double|bool|var)\s([A-Z0-9]) + paths: + include: + - "*.cs" + metadata: + description: Variable names should be lowercase + category: codestyle + technology: + - .net + impact: LOW + confidence: LOW + diff --git a/tools/getTools.go b/tools/getTools.go index 0c750423..42ee4c26 100644 --- a/tools/getTools.go +++ b/tools/getTools.go @@ -145,6 +145,7 @@ type Tool struct { func FilterToolsByConfigUsage(tools []Tool) []Tool { var filtered []Tool for _, tool := range tools { + if !tool.Settings.UsesConfigFile { filtered = append(filtered, tool) } else { diff --git a/tools/runnerUtils.go b/tools/runnerUtils.go index 46e37986..6ba9201b 100644 --- a/tools/runnerUtils.go +++ b/tools/runnerUtils.go @@ -6,24 +6,26 @@ import ( "path/filepath" ) -// ConfigFileExists checks if a specific configuration file exists in the .codacy/tools-configs/ +// ConfigFileExists checks if any of the specified configuration files exist in the .codacy/tools-configs/ // or on the root of the repository directory. // // Parameters: // - conf: The configuration object containing the tools config directory -// - fileName: The configuration file name to check for +// - fileNames: A list of configuration file names to check for // // Returns: -// - string: The relative path to the configuration file (for cmd args) -// - bool: True if the file exists, false otherwise -func ConfigFileExists(conf config.ConfigType, fileName string) (string, bool) { - generatedConfigFile := filepath.Join(conf.ToolsConfigDirectory(), fileName) - existingConfigFile := filepath.Join(conf.RepositoryDirectory(), fileName) +// - string: The relative path to the first configuration file found (for cmd args) +// - bool: True if any file exists, false otherwise +func ConfigFileExists(conf config.ConfigType, fileNames ...string) (string, bool) { + for _, fileName := range fileNames { + generatedConfigFile := filepath.Join(conf.ToolsConfigDirectory(), fileName) + existingConfigFile := filepath.Join(conf.RepositoryDirectory(), fileName) - if _, err := os.Stat(generatedConfigFile); err == nil { - return generatedConfigFile, true - } else if _, err := os.Stat(existingConfigFile); err == nil { - return existingConfigFile, true + if _, err := os.Stat(generatedConfigFile); err == nil { + return generatedConfigFile, true + } else if _, err := os.Stat(existingConfigFile); err == nil { + return existingConfigFile, true + } } return "", false diff --git a/tools/semgrepConfigCreator.go b/tools/semgrepConfigCreator.go new file mode 100644 index 00000000..6272bffe --- /dev/null +++ b/tools/semgrepConfigCreator.go @@ -0,0 +1,93 @@ +package tools + +import ( + "codacy/cli-v2/domain" + "fmt" + "os" + "path/filepath" + "strings" + + "gopkg.in/yaml.v3" +) + +// semgrepRulesFile represents the structure of the rules.yaml file +type semgrepRulesFile struct { + Rules []map[string]interface{} `yaml:"rules"` +} + +// FilterRulesFromFile extracts enabled rules from a rules.yaml file based on configuration +func FilterRulesFromFile(rulesFilePath string, config []domain.PatternConfiguration) ([]byte, error) { + // Read the rules.yaml file + data, err := os.ReadFile(rulesFilePath) + if err != nil { + return nil, fmt.Errorf("failed to read rules file: %w", err) + } + + // Parse the YAML file + var allRules semgrepRulesFile + if err := yaml.Unmarshal(data, &allRules); err != nil { + return nil, fmt.Errorf("failed to parse rules file: %w", err) + } + + // Create a map of enabled pattern IDs for faster lookup + enabledPatterns := make(map[string]bool) + for _, pattern := range config { + if pattern.Enabled && pattern.PatternDefinition.Enabled { + // Extract rule ID from pattern ID + parts := strings.SplitN(pattern.PatternDefinition.Id, "_", 2) + if len(parts) == 2 { + ruleID := parts[1] + enabledPatterns[ruleID] = true + } + } + } + + // Filter the rules based on enabled patterns + var filteredRules semgrepRulesFile + filteredRules.Rules = []map[string]interface{}{} + + for _, rule := range allRules.Rules { + // Get the rule ID + if ruleID, ok := rule["id"].(string); ok && enabledPatterns[ruleID] { + // If this rule is enabled, include it + filteredRules.Rules = append(filteredRules.Rules, rule) + } + } + + // If no rules match, return an error + if len(filteredRules.Rules) == 0 { + return nil, fmt.Errorf("no matching rules found") + } + + // Marshal the filtered rules back to YAML + return yaml.Marshal(filteredRules) +} + +// GetSemgrepConfig gets the Semgrep configuration based on the pattern configuration +func GetSemgrepConfig(config []domain.PatternConfiguration) ([]byte, error) { + // Get the default rules file location + rulesFile := filepath.Join("plugins", "tools", "semgrep", "rules.yaml") + + // Check if it exists and config is not empty + if _, err := os.Stat(rulesFile); err == nil && len(config) > 0 { + // Try to filter rules from the file + return FilterRulesFromFile(rulesFile, config) + } + + // If rules.yaml doesn't exist or config is empty, return an error + return nil, fmt.Errorf("rules.yaml not found or empty configuration") +} + +// GetDefaultSemgrepConfig gets the default Semgrep configuration +func GetDefaultSemgrepConfig() ([]byte, error) { + // Get the default rules file location + rulesFile := filepath.Join("plugins", "tools", "semgrep", "rules.yaml") + + // If the file exists, return its contents + if _, err := os.Stat(rulesFile); err == nil { + return os.ReadFile(rulesFile) + } + + // Return an error if rules.yaml doesn't exist + return nil, fmt.Errorf("rules.yaml not found") +} diff --git a/tools/semgrepConfigCreator_test.go b/tools/semgrepConfigCreator_test.go new file mode 100644 index 00000000..b22cb54a --- /dev/null +++ b/tools/semgrepConfigCreator_test.go @@ -0,0 +1,214 @@ +package tools + +import ( + "codacy/cli-v2/domain" + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/assert" + "gopkg.in/yaml.v3" +) + +// Sample rules YAML content for testing +const sampleRulesYAML = `rules: + - id: rule1 + pattern: | + $X + message: "Test rule 1" + languages: [go] + severity: INFO + - id: rule2 + pattern: | + $Y + message: "Test rule 2" + languages: [javascript] + severity: WARNING + - id: rule3 + pattern-either: + - pattern: "foo()" + - pattern: "bar()" + message: "Test rule 3" + languages: [python] + severity: ERROR +` + +// TestFilterRulesFromFile tests the FilterRulesFromFile function +func TestFilterRulesFromFile(t *testing.T) { + // Create a temporary rules file + tempDir := t.TempDir() + rulesFile := filepath.Join(tempDir, "rules.yaml") + err := os.WriteFile(rulesFile, []byte(sampleRulesYAML), 0644) + assert.NoError(t, err) + + // Test case 1: Filter with enabled rules + config := []domain.PatternConfiguration{ + { + Enabled: true, + PatternDefinition: domain.PatternDefinition{ + Id: "Semgrep_rule1", + Enabled: true, + }, + }, + { + Enabled: true, + PatternDefinition: domain.PatternDefinition{ + Id: "Semgrep_rule3", + Enabled: true, + }, + }, + } + + result, err := FilterRulesFromFile(rulesFile, config) + assert.NoError(t, err) + + // Parse the result and verify the rules + var parsedRules semgrepRulesFile + err = yaml.Unmarshal(result, &parsedRules) + assert.NoError(t, err) + assert.Equal(t, 2, len(parsedRules.Rules)) + + // Check that it contains rule1 and rule3 but not rule2 + ruleIDs := map[string]bool{} + for _, rule := range parsedRules.Rules { + id, _ := rule["id"].(string) + ruleIDs[id] = true + } + assert.True(t, ruleIDs["rule1"]) + assert.False(t, ruleIDs["rule2"]) + assert.True(t, ruleIDs["rule3"]) + + // Test case 2: No enabled rules should return an error + noEnabledConfig := []domain.PatternConfiguration{ + { + Enabled: false, + PatternDefinition: domain.PatternDefinition{ + Id: "Semgrep_rule1", + Enabled: false, + }, + }, + } + + _, err = FilterRulesFromFile(rulesFile, noEnabledConfig) + assert.Error(t, err) + assert.Contains(t, err.Error(), "no matching rules found") + + // Test case 3: Non-existent rules file should return an error + _, err = FilterRulesFromFile(filepath.Join(tempDir, "nonexistent.yaml"), config) + assert.Error(t, err) + assert.Contains(t, err.Error(), "failed to read rules file") +} + +// TestGetSemgrepConfig tests the GetSemgrepConfig function +func TestGetSemgrepConfig(t *testing.T) { + // Override the function to find rules.yaml to use our test file + originalRulesFilePath := filepath.Join("plugins", "tools", "semgrep", "rules.yaml") + + // Create a temporary rules file + tempDir := t.TempDir() + testRulesFile := filepath.Join(tempDir, "rules.yaml") + err := os.WriteFile(testRulesFile, []byte(sampleRulesYAML), 0644) + assert.NoError(t, err) + + // Create a backup of the original file if it exists + backupFilePath := "" + if _, err := os.Stat(originalRulesFilePath); err == nil { + backupFilePath = originalRulesFilePath + ".bak" + err = os.Rename(originalRulesFilePath, backupFilePath) + assert.NoError(t, err) + } + + // Ensure the directory exists + err = os.MkdirAll(filepath.Dir(originalRulesFilePath), 0755) + assert.NoError(t, err) + + // Copy our test file to the location + testFileContent, err := os.ReadFile(testRulesFile) + assert.NoError(t, err) + err = os.WriteFile(originalRulesFilePath, testFileContent, 0644) + assert.NoError(t, err) + + // Clean up after the test + defer func() { + os.Remove(originalRulesFilePath) + if backupFilePath != "" { + os.Rename(backupFilePath, originalRulesFilePath) + } + }() + + // Test with valid configuration + config := []domain.PatternConfiguration{ + { + Enabled: true, + PatternDefinition: domain.PatternDefinition{ + Id: "Semgrep_rule1", + Enabled: true, + }, + }, + } + + result, err := GetSemgrepConfig(config) + assert.NoError(t, err) + + var parsedRules semgrepRulesFile + err = yaml.Unmarshal(result, &parsedRules) + assert.NoError(t, err) + assert.Equal(t, 1, len(parsedRules.Rules)) + + // Test with empty configuration + _, err = GetSemgrepConfig([]domain.PatternConfiguration{}) + assert.Error(t, err) +} + +// TestGetDefaultSemgrepConfig tests the GetDefaultSemgrepConfig function +func TestGetDefaultSemgrepConfig(t *testing.T) { + // Override the function to find rules.yaml to use our test file + originalRulesFilePath := filepath.Join("plugins", "tools", "semgrep", "rules.yaml") + + // Create a temporary rules file + tempDir := t.TempDir() + testRulesFile := filepath.Join(tempDir, "rules.yaml") + err := os.WriteFile(testRulesFile, []byte(sampleRulesYAML), 0644) + assert.NoError(t, err) + + // Create a backup of the original file if it exists + backupFilePath := "" + if _, err := os.Stat(originalRulesFilePath); err == nil { + backupFilePath = originalRulesFilePath + ".bak" + err = os.Rename(originalRulesFilePath, backupFilePath) + assert.NoError(t, err) + } + + // Ensure the directory exists + err = os.MkdirAll(filepath.Dir(originalRulesFilePath), 0755) + assert.NoError(t, err) + + // Copy our test file to the location + testFileContent, err := os.ReadFile(testRulesFile) + assert.NoError(t, err) + err = os.WriteFile(originalRulesFilePath, testFileContent, 0644) + assert.NoError(t, err) + + // Clean up after the test + defer func() { + os.Remove(originalRulesFilePath) + if backupFilePath != "" { + os.Rename(backupFilePath, originalRulesFilePath) + } + }() + + // Test getting default config + result, err := GetDefaultSemgrepConfig() + assert.NoError(t, err) + + var parsedRules semgrepRulesFile + err = yaml.Unmarshal(result, &parsedRules) + assert.NoError(t, err) + assert.Equal(t, 3, len(parsedRules.Rules)) + + // Test when rules.yaml doesn't exist + os.Remove(originalRulesFilePath) + _, err = GetDefaultSemgrepConfig() + assert.Error(t, err) + assert.Contains(t, err.Error(), "rules.yaml not found") +} diff --git a/tools/semgrepRunner.go b/tools/semgrepRunner.go new file mode 100644 index 00000000..e2fae3cb --- /dev/null +++ b/tools/semgrepRunner.go @@ -0,0 +1,78 @@ +package tools + +import ( + "codacy/cli-v2/config" + "codacy/cli-v2/plugins" + "fmt" + "os" + "os/exec" + "path/filepath" +) + +// RunSemgrep executes Semgrep analysis on the specified directory +func RunSemgrep(workDirectory string, toolInfo *plugins.ToolInfo, files []string, outputFile string, outputFormat string) error { + // Construct base command with -m semgrep to run semgrep module + cmdArgs := []string{"scan"} + + // Defaults from https://github.com/codacy/codacy-semgrep/blob/master/internal/tool/command.go + cmdArgs = append(cmdArgs, "--max-memory", "2560") + cmdArgs = append(cmdArgs, "--timeout", "5") + cmdArgs = append(cmdArgs, "--timeout-threshold", "3") + + cmdArgs = append(cmdArgs, "--disable-version-check") + + // Add output format if specified + if outputFormat == "sarif" { + cmdArgs = append(cmdArgs, "--sarif") + } + + // Define possible Semgrep config file names + semgrepConfigFiles := []string{"semgrep.yml", "semgrep.yaml", "semgrep/semgrep.yml"} + + // Check if a config file exists in the expected location and use it if present + if configFile, exists := ConfigFileExists(config.Config, semgrepConfigFiles...); exists { + cmdArgs = append(cmdArgs, "--config", configFile) + } else { + // add --config auto only if no config file exists + cmdArgs = append(cmdArgs, "--config", "auto") + } + + // Add files to analyze - if no files specified, analyze current directory + if len(files) > 0 { + cmdArgs = append(cmdArgs, files...) + } else { + cmdArgs = append(cmdArgs, ".") + } + + // Get Semgrep binary from the specified installation path + semgrepPath := filepath.Join(toolInfo.InstallDir, "venv", "bin", "semgrep") + + // Create Semgrep command + cmd := exec.Command(semgrepPath, cmdArgs...) + cmd.Dir = workDirectory + + if outputFile != "" { + // If output file is specified, create it and redirect output + var outputWriter *os.File + var err error + outputWriter, err = os.Create(filepath.Clean(outputFile)) + if err != nil { + return fmt.Errorf("failed to create output file: %w", err) + } + defer outputWriter.Close() + cmd.Stdout = outputWriter + } else { + cmd.Stdout = os.Stdout + } + cmd.Stderr = os.Stderr + + // Run Semgrep + if err := cmd.Run(); err != nil { + // Semgrep returns non-zero exit code when it finds issues, which is expected + if _, ok := err.(*exec.ExitError); !ok { + return fmt.Errorf("failed to run semgrep: %w", err) + } + } + + return nil +} diff --git a/tools/semgrepRunner_test.go b/tools/semgrepRunner_test.go new file mode 100644 index 00000000..235bf0d2 --- /dev/null +++ b/tools/semgrepRunner_test.go @@ -0,0 +1,45 @@ +package tools + +import ( + "codacy/cli-v2/plugins" + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestRunSemgrepWithSpecificFiles(t *testing.T) { + homeDirectory, err := os.UserHomeDir() + if err != nil { + t.Fatalf("Failed to get home directory: %v", err) + } + currentDirectory, err := os.Getwd() + if err != nil { + t.Fatalf("Failed to get current directory: %v", err) + } + + // Set up test directories and files + testDirectory := filepath.Join(currentDirectory, "testdata", "repositories", "semgrep") + tempResultFile := filepath.Join(os.TempDir(), "semgrep-specific.sarif") + defer os.Remove(tempResultFile) + + // Create tool info for semgrep + toolInfo := &plugins.ToolInfo{ + InstallDir: filepath.Join(homeDirectory, ".cache/codacy/tools/semgrep@1.78.0"), + } + + // Specify files to analyze + filesToAnalyze := []string{"sample.js"} + + // Run Semgrep analysis on specific files + err = RunSemgrep(testDirectory, toolInfo, filesToAnalyze, tempResultFile, "sarif") + if err != nil { + t.Fatalf("Failed to run semgrep on specific files: %v", err) + } + + // Verify file exists and has content + fileInfo, err := os.Stat(tempResultFile) + assert.NoError(t, err, "Failed to stat output file") + assert.Greater(t, fileInfo.Size(), int64(0), "Output file should not be empty") +} diff --git a/tools/testdata/repositories/semgrep/expected.sarif b/tools/testdata/repositories/semgrep/expected.sarif new file mode 100644 index 00000000..221a5d5a --- /dev/null +++ b/tools/testdata/repositories/semgrep/expected.sarif @@ -0,0 +1,64 @@ +{ + "version": "2.1.0", + "$schema": "http://json.schemastore.org/sarif-2.1.0-rtm.5", + "runs": [ + { + "tool": { + "driver": { + "name": "Semgrep", + "version": "1.41.0", + "informationUri": "https://semgrep.dev", + "rules": [ + { + "id": "hardcoded-credentials", + "name": "Hardcoded Credentials", + "shortDescription": { + "text": "Hardcoded API key detected" + }, + "fullDescription": { + "text": "Found hardcoded API key. This is a security risk." + }, + "defaultConfiguration": { + "level": "warning" + }, + "help": { + "text": "API keys and other credentials should not be hardcoded in source files. Use environment variables or secure credential storage instead." + } + } + ] + } + }, + "artifacts": [ + { + "location": { + "uri": "testdata/repositories/semgrep/sample.js" + } + } + ], + "results": [ + { + "ruleId": "hardcoded-credentials", + "level": "warning", + "message": { + "text": "Hardcoded API key detected" + }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "testdata/repositories/semgrep/sample.js" + }, + "region": { + "startLine": 3, + "startColumn": 16, + "endLine": 3, + "endColumn": 32 + } + } + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/tools/testdata/repositories/semgrep/sample.js b/tools/testdata/repositories/semgrep/sample.js new file mode 100644 index 00000000..8f430840 --- /dev/null +++ b/tools/testdata/repositories/semgrep/sample.js @@ -0,0 +1,10 @@ +// Sample JavaScript file for Semgrep testing + +const API_KEY = "1234567890abcdef"; // Hardcoded credential for testing + +function helloWorld() { + console.log("Hello, world!"); + console.log("Using API Key:", API_KEY); +} + +helloWorld(); \ No newline at end of file