{
  "$defs": {
    "patterns-content": {
      "type": "array",
      "title": "Return finding where all of the nested conditions are true",
      "items": {
        "anyOf": [
          {
            "$ref": "#/$defs/patterns"
          },
          {
            "$ref": "#/$defs/pattern-either"
          },
          {
            "$ref": "#/$defs/focus-metavariable"
          },
          {
            "$ref": "#/$defs/pattern-inside"
          },
          {
            "$ref": "#/$defs/pattern-not-inside"
          },
          {
            "$ref": "#/$defs/pattern-not"
          },
          {
            "$ref": "#/$defs/pattern"
          },
          {
            "$ref": "#/$defs/pattern-regex"
          },
          {
            "$ref": "#/$defs/pattern-not-regex"
          },
          {
            "$ref": "#/$defs/pattern-where-python"
          },
          {
            "$ref": "#/$defs/metavariable-analysis"
          },
          {
            "$ref": "#/$defs/metavariable-regex"
          },
          {
            "$ref": "#/$defs/metavariable-pattern"
          },
          {
            "$ref": "#/$defs/metavariable-comparison"
          }
        ]
      }
    },
    "pattern-either-content": {
      "type": "array",
      "title": "Return finding where any of the nested conditions are true",
      "items": {
        "anyOf": [
          {
            "$ref": "#/$defs/patterns"
          },
          {
            "$ref": "#/$defs/pattern-either"
          },
          {
            "$ref": "#/$defs/pattern-inside"
          },
          {
            "$ref": "#/$defs/pattern"
          },
          {
            "$ref": "#/$defs/pattern-regex"
          }
        ]
      }
    },
    "taint-content": {
      "type": "array",
      "items": {
        "anyOf": [
          {
            "type": "object",
            "properties": {
              "pattern": {
                "title": "Return finding where Semgrep pattern matches exactly",
                "type": "string"
              },
              "pattern-regex": {
                "title": "Return finding where regular expression matches exactly",
                "type": "string"
              },
              "patterns": {
                "$ref": "#/$defs/patterns-content"
              },
              "pattern-either": {
                "$ref": "#/$defs/pattern-either-content"
              }
            },
            "oneOf": [
              {
                "required": ["pattern"],
                "not": {
                  "anyOf": [
                    {
                      "required": ["patterns"]
                    },
                    {
                      "required": ["pattern-either"]
                    },
                    {
                      "required": ["pattern-regex"]
                    }
                  ]
                }
              },
              {
                "required": ["patterns"],
                "not": {
                  "anyOf": [
                    {
                      "required": ["pattern"]
                    },
                    {
                      "required": ["pattern-either"]
                    },
                    {
                      "required": ["pattern-regex"]
                    }
                  ]
                }
              },
              {
                "required": ["pattern-either"],
                "not": {
                  "anyOf": [
                    {
                      "required": ["pattern"]
                    },
                    {
                      "required": ["patterns"]
                    },
                    {
                      "required": ["pattern-regex"]
                    }
                  ]
                }
              },
              {
                "required": ["pattern-regex"],
                "not": {
                  "anyOf": [
                    {
                      "required": ["pattern"]
                    },
                    {
                      "required": ["patterns"]
                    },
                    {
                      "required": ["pattern-either"]
                    }
                  ]
                }
              }
            ]
          }
        ]
      }
    },
    "r2c-internal-project-depends-on-content": {
      "type": "object",
      "title": "One or more dependencies that the project contains in a lock file",
      "properties": {
        "namespace": {
          "type": "string"
        },
        "package": {
          "type": "string"
        },
        "version": {
          "type": "string"
        },
        "depends-on-either": {
          "type": "array",
          "properties": {
            "namespace": {
              "type": "string"
            },
            "package": {
              "type": "string"
            },
            "version": {
              "type": "string"
            }
          },
          "additionalProperties": false,
          "required": ["namespace", "package", "version"]
        }
      },
      "oneOf": [
        {
          "required": ["namespace", "package", "version"],
          "not": {
            "required": ["depends-on-either"]
          }
        },
        {
          "required": ["depends-on-either"],
          "not": {
            "anyOf": [
              {
                "required": ["namespace"]
              },
              {
                "required": ["package"]
              },
              {
                "required": ["version"]
              }
            ]
          }
        }
      ]
    },
    "join-content": {
      "type": "object",
      "title": "Join one or more rules together based on metavariable contents",
      "properties": {
        "refs": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "rule": {
                "type": "string"
              },
              "renames": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "from": {
                      "type": "string"
                    },
                    "to": {
                      "type": "string"
                    }
                  }
                }
              },
              "as": {
                "type": "string"
              }
            },
            "additionalProperties": false
          }
        },
        "rules": {
          "type": "array",
          "items": {
            "type": "object",
            "required": ["id", "languages"],
            "oneOf": [
              {
                "required": ["pattern"]
              },
              {
                "required": ["patterns"]
              },
              {
                "required": ["pattern-sources", "pattern-sinks"]
              }
            ],
            "properties": {
              "id": {
                "$ref": "#/$defs/id"
              },
              "languages": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "pattern": {
                "type": "string"
              },
              "patterns": {
                "$ref": "#/$defs/patterns-content"
              },
              "mode": {
                "enum": ["search", "taint"]
              },
              "pattern-sources": {
                "$ref": "#/$defs/taint-content"
              },
              "pattern-propagators": {
                "$ref": "#/$defs/taint-content"
              },
              "pattern-sinks": {
                "$ref": "#/$defs/taint-content"
              },
              "pattern-sanitizers": {
                "$ref": "#/$defs/taint-content"
              }
            },
            "additionalProperties": false
          }
        },
        "on": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "additionalProperties": false
      },
      "additionalProperties": false
    },
    "metavariable-analysis": {
      "type": "object",
      "properties": {
        "metavariable-analysis": {
          "type": "object",
          "properties": {
            "analyzer": {
              "type": "string"
            },
            "metavariable": {
              "type": "string"
            },
            "options": {
              "type": "object"
            }
          },
          "required": ["analyzer", "metavariable"],
          "additionalProperties": false
        }
      },
      "required": ["metavariable-analysis"],
      "additionalProperties": false
    },
    "metavariable-regex": {
      "type": "object",
      "properties": {
        "metavariable-regex": {
          "type": "object",
          "properties": {
            "metavariable": {
              "type": "string"
            },
            "regex": {
              "type": "string"
            },
            "constant-propagation": {
              "type": "boolean"
            }
          },
          "required": ["metavariable", "regex"],
          "additionalProperties": false
        }
      },
      "required": ["metavariable-regex"],
      "additionalProperties": false
    },
    "metavariable-pattern": {
      "type": "object",
      "properties": {
        "metavariable-pattern": {
          "type": "object",
          "properties": {
            "metavariable": {
              "type": "string"
            },
            "language": {
              "type": "string"
            },
            "pattern": {
              "title": "Return finding where Semgrep pattern matches exactly",
              "type": "string"
            },
            "pattern-regex": {
              "title": "Return finding where regular expression matches exactly",
              "type": "string"
            },
            "patterns": {
              "$ref": "#/$defs/patterns-content"
            },
            "pattern-either": {
              "$ref": "#/$defs/pattern-either-content"
            }
          },
          "required": ["metavariable"],
          "oneOf": [
            {
              "required": ["pattern"],
              "not": {
                "anyOf": [
                  {
                    "required": ["patterns"]
                  },
                  {
                    "required": ["pattern-either"]
                  },
                  {
                    "required": ["pattern-regex"]
                  }
                ]
              }
            },
            {
              "required": ["patterns"],
              "not": {
                "anyOf": [
                  {
                    "required": ["pattern"]
                  },
                  {
                    "required": ["pattern-either"]
                  },
                  {
                    "required": ["pattern-regex"]
                  }
                ]
              }
            },
            {
              "required": ["pattern-either"],
              "not": {
                "anyOf": [
                  {
                    "required": ["pattern"]
                  },
                  {
                    "required": ["patterns"]
                  },
                  {
                    "required": ["pattern-regex"]
                  }
                ]
              }
            },
            {
              "required": ["pattern-regex"],
              "not": {
                "anyOf": [
                  {
                    "required": ["pattern"]
                  },
                  {
                    "required": ["patterns"]
                  },
                  {
                    "required": ["pattern-either"]
                  }
                ]
              }
            }
          ],
          "additionalProperties": false
        }
      },
      "required": ["metavariable-pattern"],
      "additionalProperties": false
    },
    "metavariable-comparison": {
      "type": "object",
      "properties": {
        "metavariable-comparison": {
          "type": "object",
          "properties": {
            "metavariable": {
              "type": "string"
            },
            "comparison": {
              "type": "string"
            },
            "strip": {
              "type": "boolean"
            },
            "base": {
              "type": "integer"
            }
          },
          "required": ["comparison"],
          "additionalProperties": false
        }
      },
      "required": ["metavariable-comparison"],
      "additionalProperties": false
    },
    "pattern": {
      "type": "object",
      "properties": {
        "pattern": {
          "title": "Return finding where Semgrep pattern matches exactly",
          "type": "string"
        }
      },
      "required": ["pattern"],
      "additionalProperties": false
    },
    "pattern-regex": {
      "type": "object",
      "properties": {
        "pattern-regex": {
          "title": "Return finding where regular expression matches",
          "type": "string"
        }
      },
      "required": ["pattern-regex"],
      "additionalProperties": false
    },
    "pattern-not-regex": {
      "type": "object",
      "properties": {
        "pattern-not-regex": {
          "title": "Do not return finding where regular expression matches",
          "type": "string"
        }
      },
      "required": ["pattern-not-regex"],
      "additionalProperties": false
    },
    "patterns": {
      "type": "object",
      "properties": {
        "patterns": {
          "title": "Return finding where all of the nested conditions are true",
          "$ref": "#/$defs/patterns-content"
        }
      },
      "required": ["patterns"],
      "additionalProperties": false
    },
    "pattern-either": {
      "type": "object",
      "properties": {
        "pattern-either": {
          "title": "Return finding where any of the nested conditions are true",
          "$ref": "#/$defs/pattern-either-content"
        }
      },
      "required": ["pattern-either"],
      "additionalProperties": false
    },
    "focus-metavariable": {
      "type": "object",
      "properties": {
        "focus-metavariable": {
          "title": "Focus on what a given metavariable is matching",
          "type": "string"
        }
      },
      "required": ["focus-metavariable"],
      "additionalProperties": false
    },
    "pattern-inside": {
      "type": "object",
      "properties": {
        "pattern-inside": {
          "title": "Return findings only from within snippets Semgrep pattern matches",
          "type": "string"
        }
      },
      "required": ["pattern-inside"],
      "additionalProperties": false
    },
    "pattern-not-inside": {
      "type": "object",
      "properties": {
        "pattern-not-inside": {
          "title": "Do not return findings from within snippets Semgrep pattern matches",
          "type": "string"
        }
      },
      "required": ["pattern-not-inside"],
      "additionalProperties": false
    },
    "pattern-not": {
      "type": "object",
      "properties": {
        "pattern-not": {
          "title": "Do not return finding where Semgrep pattern matches exactly",
          "type": "string"
        }
      },
      "required": ["pattern-not"],
      "additionalProperties": false
    },
    "pattern-where-python": {
      "type": "object",
      "properties": {
        "pattern-where-python": {
          "title": "Return finding where Python expression returns true",
          "type": "string"
        }
      },
      "required": ["pattern-where-python"],
      "additionalProperties": false
    },
    "path-array": {
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "id": {
      "title": "Rule ID to attach to findings",
      "type": "string"
    }
  },
  "$id": "https://raw.githubusercontent.com/returntocorp/semgrep-interfaces/main/rule_schema.yaml",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "properties": {
    "rules": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "$ref": "#/$defs/id"
          },
          "version": {
            "title": "Version of rule",
            "type": "string"
          },
          "message": {
            "title": "Description to attach to findings",
            "type": "string"
          },
          "mode": {
            "default": "search",
            "enum": ["search", "taint", "join", "extract"]
          },
          "languages": {
            "title": "Languages this pattern should run on",
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "paths": {
            "title": "Path globs this pattern should run on",
            "type": "object",
            "properties": {
              "include": {
                "$ref": "#/$defs/path-array"
              },
              "exclude": {
                "$ref": "#/$defs/path-array"
              }
            },
            "additionalProperties": false
          },
          "severity": {
            "title": "Severity to report alongside this finding",
            "enum": ["ERROR", "WARNING", "INFO", "INVENTORY", "EXPERIMENT"]
          },
          "pattern-sinks": {
            "$ref": "#/$defs/taint-content"
          },
          "pattern-sources": {
            "$ref": "#/$defs/taint-content"
          },
          "pattern-propagators": {
            "$ref": "#/$defs/taint-content"
          },
          "pattern-sanitizers": {
            "$ref": "#/$defs/taint-content"
          },
          "join": {
            "$ref": "#/$defs/join-content"
          },
          "fix": {
            "title": "Replacement text to fix matched code. Can use matched metavariables.",
            "type": "string"
          },
          "fix-regex": {
            "type": "object",
            "title": "Replacement regex to fix matched code.",
            "properties": {
              "count": {
                "title": "Replace up to this many regex matches",
                "type": "integer"
              },
              "regex": {
                "title": "Regular expression to find in matched code",
                "type": "string"
              },
              "replacement": {
                "title": "Code to replace the regular expression match with. Can use capture groups.",
                "type": "string"
              }
            },
            "required": ["regex", "replacement"],
            "additionalProperties": false
          },
          "metadata": {
            "title": "Arbitrary structured data for your own reference",
            "type": "object"
          },
          "options": {
            "title": "Options object to enable/disable certain matching features in semgrep-core",
            "type": "object"
          },
          "pattern": {
            "title": "Return finding where Semgrep pattern matches exactly",
            "type": "string"
          },
          "pattern-regex": {
            "title": "Return finding where regular expression matches exactly",
            "type": "string"
          },
          "patterns": {
            "$ref": "#/$defs/patterns-content"
          },
          "pattern-either": {
            "$ref": "#/$defs/pattern-either-content"
          },
          "r2c-internal-project-depends-on": {
            "$ref": "#/$defs/r2c-internal-project-depends-on-content"
          },
          "extract": {
            "title": "Metavariable whose content to use as the extracted result for subsequent rules",
            "type": "string"
          },
          "dest-language": {
            "title": "Language to process the extracted result of this rule as",
            "type": "string"
          },
          "reduce": {
            "title": "Method of intrafile match reduction",
            "enum": ["concat", "separate"],
            "default": "separate"
          }
        },
        "additionalProperties": false,
        "allOf": [
          {
            "if": {
              "properties": {
                "mode": {
                  "const": "extract"
                }
              },
              "required": ["mode"]
            },
            "then": {
              "required": ["id", "languages", "dest-language", "extract"],
              "oneOf": [
                {
                  "required": ["pattern"]
                },
                {
                  "required": ["patterns"]
                },
                {
                  "required": ["pattern-either"]
                },
                {
                  "required": ["pattern-regex"]
                }
              ],
              "properties": {
                "message": false,
                "severity": false,
                "pattern-sinks": false,
                "pattern-sources": false,
                "pattern-propagators": false,
                "pattern-sanitizers": false,
                "join": false
              }
            }
          },
          {
            "if": {
              "properties": {
                "mode": {
                  "const": "taint"
                }
              },
              "required": ["mode"]
            },
            "then": {
              "required": [
                "id",
                "message",
                "languages",
                "severity",
                "pattern-sinks",
                "pattern-sources"
              ],
              "properties": {
                "extract": false,
                "dest-language": false,
                "reduce": false,
                "pattern": false,
                "patterns": false,
                "pattern-either": false,
                "pattern-regex": false,
                "join": false
              }
            }
          },
          {
            "if": {
              "properties": {
                "mode": {
                  "const": "join"
                }
              },
              "required": ["mode"]
            },
            "then": {
              "required": ["id", "message", "severity", "join"],
              "properties": {
                "extract": false,
                "dest-language": false,
                "reduce": false,
                "patterns": false,
                "pattern": false,
                "pattern-either": false,
                "pattern-regex": false,
                "pattern-sinks": false,
                "pattern-sources": false,
                "pattern-propagators": false,
                "pattern-sanitizers": false
              }
            }
          },
          {
            "if": {
              "properties": {
                "mode": {
                  "const": "search"
                }
              }
            },
            "then": {
              "required": ["id", "message", "languages", "severity"],
              "if": {
                "anyOf": [
                  {
                    "required": ["pattern"]
                  },
                  {
                    "required": ["patterns"]
                  },
                  {
                    "required": ["pattern-either"]
                  },
                  {
                    "required": ["pattern-regex"]
                  }
                ]
              },
              "then": {
                "oneOf": [
                  {
                    "required": ["pattern"]
                  },
                  {
                    "required": ["patterns"]
                  },
                  {
                    "required": ["pattern-either"]
                  },
                  {
                    "required": ["pattern-regex"]
                  }
                ]
              },
              "else": {
                "oneOf": [
                  {
                    "required": ["pattern"]
                  },
                  {
                    "required": ["patterns"]
                  },
                  {
                    "required": ["pattern-either"]
                  },
                  {
                    "required": ["pattern-regex"]
                  },
                  {
                    "required": ["r2c-internal-project-depends-on"]
                  }
                ]
              },
              "properties": {
                "extract": false,
                "dest-language": false,
                "reduce": false,
                "pattern-sinks": false,
                "pattern-sources": false,
                "pattern-propagators": false,
                "pattern-sanitizers": false,
                "join": false
              }
            }
          }
        ]
      }
    }
  },
  "type": "object"
}
