JSPM

  • Created
  • Published
  • Downloads 850
  • Score
    100M100P100Q134004F
  • License Apache-2.0

Grafana Plugin Validator

Package Exports

    This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@grafana/plugin-validator) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

    Readme

    Grafana Plugin Validator

    License Go Report Card

    This tool helps speed up the process of publishing plugins to Grafana.com. It runs a series of analyzers to ensure plugins are following best practices, checking for security and structural issues, as well as specific requirements related to publishing. A general overview of these requirements can be found here: https://grafana.com/docs/grafana/latest/developers/plugins/publishing-and-signing-criteria/.

    It requires a path to a remote or local ZIP archive of the plugin to be specified, for example:

    • Remote: https://github.com/grafana/clock-panel/releases/download/v2.1.2/grafana-clock-panel-2.1.2.zip
    • Local: file://Users/me/Downloads/grafana-clock-panel-2.1.2.zip

    You can additionally provide a link to the source code for the project with -sourceCodeUri to enable additional analyzers such as the Vulnerability Scan.

    Installation and usage

    Ensure that your version of Go matches the one specified in the go.mod file to avoid compatibility issues

    It is easiest to run the tool using the Docker image as it contains all the security scanning tools needed for the full set of analyzers - so you don't need to have these additional tools installed on your system.

    docker run --pull=always grafana/plugin-validator-cli [options] [http://yourdomain/plugin_archive.zip]

    Example 1 (basic)

    docker run --pull=always grafana/plugin-validator-cli https://github.com/grafana/clock-panel/releases/download/v2.1.2/grafana-clock-panel-2.1.2.zip

    Example 2 (specifying source code location)

    docker run --pull=always grafana/plugin-validator-cli -sourceCodeUri https://github.com/grafana/clock-panel/tree/v2.1.2 https://github.com/grafana/clock-panel/releases/download/v2.1.2/grafana-clock-panel-2.1.2.zip

    Using a local archive file with Docker

    To run the tool with a local archive you will need to mount it as a docker volume. Here's an example:

    docker run --pull=always -v /path/to/plugin_archive.zip:/archive.zip grafana/plugin-validator-cli /archive.zip

    [!NOTE] If using relative paths your path must start with ./

    Using a local archive file and local source code

    docker run --pull=always -v /path/to/plugin_archive.zip:/archive.zip -v /path/to/source_code:/source_code grafana/plugin-validator-cli -sourceCodeUri file:///source_code /archive.zip

    [!NOTE] If using relative paths your path must start with ./

    NPX

    npx -y @grafana/plugin-validator@latest -sourceCodeUri [options] [path/to/plugin_archive.zip]

    Locally

    First you must compile and install it:

    git clone git@github.com:grafana/plugin-validator.git
    cd plugin-validator/pkg/cmd/plugincheck2
    go install

    Then you can run the utility:

    plugincheck2 -sourceCodeUri [source_code_location/] [plugin_archive.zip]

    MCP Server (for AI assistants)

    The plugin validator can be used as an MCP (Model Context Protocol) server, allowing AI assistants like Claude, Cline, and other MCP-compatible tools to validate Grafana plugins.

    See the MCP Server README for configuration instructions.

    Generating local files For validation

    You must create a .zip archive containing the dist/ directory but named as your plugin ID:

    PLUGIN_ID=$(grep '"id"' < src/plugin.json | sed -E 's/.*"id" *: *"(.*)".*/\1/')
    cp -r dist "${PLUGIN_ID}"
    zip -qr "${PLUGIN_ID}.zip" "${PLUGIN_ID}"
    npx @grafana/plugin-validator@latest -sourceCodeUri file://. "${PLUGIN_ID}.zip"

    You can optionally remove the files that were generated:

    rm -r "${PLUGIN_ID}" "${PLUGIN_ID}.zip"

    Options

    Additional options can be passed to the tool:

    ❯ plugincheck2 -help
    Usage plugincheck2:
      -config string (optional)
            Path to configuration file
      -sourceCodeUri string (optional)
            URI to the source code of the plugin. If set, the source code will be downloaded and analyzed. This can be a ZIP file URL, a URL to git repository or a local file (starting with `file://`)
      -strict (optional)
            If set, plugincheck returns non-zero exit code for warnings
      -checksum string (optional)
            If set, the checksum of the plugin archive will be checked against this value. MD5 and SHA256 are supported.
      -analyzer string (optional)
            If set, only an specific analyzer and it's dependencies will run.
      -severity string (optional)
            If used, it will set the severity of the analyzer (it has the highest priority).
    

    Using a configuration file

    You can pass a configuration YAML file to the validator with the -config option. Several configuration examples are available to use here: https://github.com/grafana/plugin-validator/tree/main/config.

    Enabling and disabling analyzers via config

    If you want to disable an specific check (analyzer) you can define this in your configuration file, adding an analyzers section, and specifying which analyzer or analyzer rules to enable and disable.

    For example, disable the version analyzer:

    global:
      enabled: true
      jsonOutput: false
      reportAll: false
    
    analyzers:
      version:
        enabled: false

    You can also disable specific rules or change their severity level:

    global:
      enabled: true
      jsonOutput: false
      reportAll: false
    
    analyzers:
      readme:
        rules:
          missing-readme:
            enabled: true
            severity: warning

    Severity levels could be: error, warning, or ok.

    Note: Grafana Labs enforces its own configuration for plugins submissions and your own config file can't change these rules.

    Excluding a plugin from an analyzer or rule

    It's also possible to exclude a specific plugin from an analyzer or a specific rule within an analyzer. This is useful when a particular check is not applicable to your plugin.

    To disable an entire analyzer for a plugin, add an exceptions list with the plugin ID.

    analyzers:
      some-analyzer:
        enabled: true
        # This entire analyzer will be skipped for 'my-plugin-id'
        exceptions:
          - my-plugin-id

    To disable a single rule for a plugin, add the exceptions list to the rule's configuration.

    analyzers:
      some-analyzer:
        rules:
          some-rule:
            enabled: true
            # This rule will be skipped for 'my-plugin-id'
            exceptions:
              - my-plugin-id

    Source code

    You can specify the location of the plugin source code to the validator with the -sourceCodeUri option. Doing so allows for additional analyzers to be run and for a more complete scan.

    Supported remote Git services

    The following public Git services are supported:

    • GitHub
    • GitLab
    • Bitbucket

    Private repositories are not currently supported.

    Make sure to include the ref (branch or tag) of the corresponding source code.

    For example: you are validating version v2.1.2 and your project is in GitHub. Make sure you create a corresponding tag or branch and use the URL https://github.com/grafana/clock-panel/tree/v2.1.2.

    Debug mode

    You can run the validator in debug mode to get more information about the running checks and possible errors.

    Docker:

    docker run --pull=always -e DEBUG=1 grafana/plugin-validator-cli -sourceCodeUri https://github.com/grafana/clock-panel/tree/v2.1.2 https://github.com/grafana/clock-panel/releases/download/v2.1.2/grafana-clock-panel-2.1.2.zip

    NPX:

    DEBUG=1 npx -y @grafana/plugin-validator@latest -sourceCodeUri https://github.com/grafana/clock-panel/tree/v2.1.2 https://github.com/grafana/clock-panel/releases/download/v2.1.2/grafana-clock-panel-2.1.2.zip

    Locally:

    DEBUG=1 plugincheck2 -sourceCodeUri https://github.com/grafana/clock-panel/tree/v2.1.2 https://github.com/grafana/clock-panel/releases/download/v2.1.2/grafana-clock-panel-2.1.2.zip

    LLM provider configuration

    The llmreview and codediff analyzers use an LLM to review plugin source code. Three providers are supported: Anthropic, OpenAI, and Google (Gemini).

    Set one of the following environment variables to enable LLM-based analysis. The first key found (in the order below) is used:

    Environment Variable Provider Default Model
    ANTHROPIC_API_KEY Anthropic claude-opus-4-6
    OPENAI_API_KEY OpenAI gpt-5.4
    GEMINI_API_KEY Google gemini-3.1-flash-lite-preview

    Example:

    ANTHROPIC_API_KEY=sk-ant-... plugincheck2 -sourceCodeUri https://github.com/org/repo/tree/v1.0.0 plugin.zip

    You can skip individual LLM analyzers with SKIP_LLM_REVIEW=1 or SKIP_LLM_CODEDIFF=1.

    Security tools

    This validator makes uses of the following open source security tools:

    If you run the validator locally or via NPX you can benefit from installing these tools in your system to make them part of your validation checks.


    Analyzers

    The tool runs a series of analyzers to ensure submitted plugins are following best practices, and speed up the process of approving a plugin for publishing, detailed in the table below. The Analyzer column includes the name required for altering the behavior of a given check in a configuration file. The Dependencies column specifies whether the analyzer requires the source code for the plugin to be provided with sourceCodeUri or for any additional security scanning tools to be present.

    Analyzer Description Dependencies
    Archive Name / archivename The name of the archive should be correctly formatted. None
    Archive Structure / archive Ensures the contents of the zip file have the expected layout. None
    Backend Binary / backendbinary Validates the consistency between the existence of a binary file and plugin.json declarations for backend or alerting. None
    Backend Debug / backenddebug Checks that the standalone debug files for backend plugins are not present. None
    Binary Permissions / binarypermissions For datasources and apps with binaries, this ensures the plugin can run when extracted on a system. None
    Broken Links / brokenlinks Detects if any URL doesn't resolve to a valid location. None
    Build Tools / buildtools Checks that the plugin uses Grafana's standard create-plugin build tooling. None
    Changelog (exists) / changelog Ensures a CHANGELOG.md file exists within the zip file. None
    Checksum / checksum Validates that the passed checksum (as a validator arg) is the one calculated from the archive file. checksum
    Circular Dependencies / circulardependencies Ensures that there aren't any circular dependencies between plugins (plugin.json, dependencies.plugins field). None
    Code Diff / codediff API key for one of: Anthropic (ANTHROPIC_API_KEY), OpenAI (OPENAI_API_KEY), or Google (GEMINI_API_KEY)
    Code Rules / code-rules Checks for forbidden access to environment variables, file system or use of syscall module. semgrep, sourceCodeUri
    Developer Jargon / jargon Generally discourages use of code jargon in the documentation. None
    Discoverability / discoverability Warns about missing keywords and description that are used for plugin indexing in the catalog. None
    Go Manifest / go-manifest Validates the build manifest. None
    Go Security Checker / go-sec Inspects source code for security problems by scanning the Go AST. gosec, sourceCodeUri
    JS Source Map / jsMap Checks for required module.js.map file(s) in archive. sourceCodeUri
    Legacy Grafana Toolkit usage / legacybuilder Detects the usage of the not longer supported Grafana Toolkit. None
    Legacy Platform / legacyplatform Detects use of Angular which is deprecated. None
    License Type / license Checks the declared license is one of: BSD, MIT, Apache 2.0, LGPL3, GPL3, AGPL3. None
    LLM Review / llmreview Runs the code through an LLM to check for security issues or disallowed usage. API key for one of: Anthropic (ANTHROPIC_API_KEY), OpenAI (OPENAI_API_KEY), or Google (GEMINI_API_KEY)
    Logos / logos Detects whether the plugin includes small and large logos to display in the plugin catalog. None
    Manifest (Signing) / manifest When a plugin is signed, the zip file will contain a signed MANIFEST.txt file. None
    Metadata / metadata Checks that plugin.json exists and is valid. None
    Metadata Grafana Dependency / grafanadependency Checks that dependencies.grafanaDependency in plugin.json is valid. None
    Metadata Paths / metadatapaths Ensures all paths are valid and images referenced exist. None
    Metadata Validity / metadatavalid Ensures metadata is valid and matches plugin schema. None
    module.js (exists) / modulejs All plugins require a module.js to be loaded. None
    Nested includes metadata / includesnested Validates that nested plugins have the correct metadata. None
    Nested Metadata / nestedmetadata Recursively checks that all plugin.json exist and are valid. None
    No Tracking Scripts / trackingscripts Detects if there are any known tracking scripts, which are not allowed. None
    Organization (exists) / org Verifies the org specified in the plugin ID exists. None
    package.json / packagejson Ensures that package.json exists and the version matches the plugin.json None
    Plugin Name formatting / pluginname Validates the plugin ID used conforms to our naming convention. None
    Provenance attestation validation / provenance Validates the provenance attestation if the plugin was built with a pipeline supporting provenance attestation (e.g Github Actions). None
    Published / published-plugin Detects whether any version of this plugin exists in the Grafana plugin catalog currently. None
    Readme (exists) / readme Ensures a README.md file exists within the zip file. None
    Restrictive Dependency / restrictivedep Specifies a valid range of Grafana versions that work with this version of the plugin. None
    Safe Links / safelinks Checks that links from plugin.json are safe. None
    Screenshots / screenshots Screenshots are specified in plugin.json that will be used in the Grafana plugin catalog. None
    SDK Usage / sdkusage Ensures that grafana-plugin-sdk-go is up-to-date. None
    Signature / signature Ensures the plugin has a valid signature. None
    Source Code / sourcecode A comparison is made between the zip file and the source code to ensure what is released matches the repo associated with it. sourceCodeUri
    Sponsorship Link / sponsorshiplink Checks if a sponsorship link is specified in plugin.json that will be shown in the Grafana plugin catalog for users to support the plugin developer. None
    Type Suffix (panel/app/datasource) / typesuffix Ensures the plugin has a valid type specified. None
    Unique README.md / templatereadme Ensures the plugin doesn't re-use the template from the create-plugin tool. None
    Unsafe SVG / unsafesvg Checks if any svg files are safe based on a whitelist of elements and attributes. None
    Version / version Ensures the version submitted is newer than the currently published plugin. If this is a new/unpublished plugin, this is skipped. None
    Virus Scan / virusscan Runs a virus scan on the plugin archive and source code using clamscan (clamav). clamscan
    Vulnerability Scanner / osv-scanner Detects critical vulnerabilities in Go modules and yarn lock files. osv-scanner, sourceCodeUri

    Output

    By default, the tool outputs results in plain text as shown below.

    Default:

    warning: README.md: possible broken link: https://www.d3js.org (404 Not Found)
    detail: README.md might contain broken links. Check that all links are valid and publicly accessible.
    warning: README.md contains developer jargon: (yarn)
    detail: Move any developer and contributor documentation to a separate file and link to it from the README.md. For example, CONTRIBUTING.md, DEVELOPMENT.md, etc.
    error: osv-scanner detected a critical severity issue
    detail: SEVERITY: CRITICAL in package immer, vulnerable to CVE-2021-23436
    error: osv-scanner detected a critical severity issue
    detail: SEVERITY: CRITICAL in package json-schema, vulnerable to CVE-2021-3918
    error: Plugin version 0.0.9 is invalid.
    detail: The submitted plugin version 0.0.9 is not greater than the latest published version 0.0.9 on grafana.com.

    This can be changed to JSON by passing a configuration file which includes:

    global:
      jsonOutput: true

    Resulting in output similar to:

    {
      "id": "briangann-gauge-panel",
      "version": "0.0.9",
      "plugin-validator": {
        "brokenlinks": [
          {
            "Severity": "warning",
            "Title": "README.md: possible broken link: https://www.d3js.org (404 Not Found)",
            "Detail": "README.md might contain broken links. Check that all links are valid and publicly accessible.",
            "Name": "broken-link"
          }
        ],
        "jargon": [
          {
            "Severity": "warning",
            "Title": "README.md contains developer jargon: (yarn)",
            "Detail": "Move any developer and contributor documentation to a separate file and link to it from the README.md. For example, CONTRIBUTING.md, DEVELOPMENT.md, etc.",
            "Name": "developer-jargon"
          }
        ],
        "osv-scanner": [
          {
            "Severity": "error",
            "Title": "osv-scanner detected a critical severity issue",
            "Detail": "SEVERITY: CRITICAL in package immer, vulnerable to CVE-2021-23436",
            "Name": "osv-scanner-critical-severity-vulnerabilities-detected"
          },
          {
            "Severity": "error",
            "Title": "osv-scanner detected a critical severity issue",
            "Detail": "SEVERITY: CRITICAL in package json-schema, vulnerable to CVE-2021-3918",
            "Name": "osv-scanner-critical-severity-vulnerabilities-detected"
          },
        ],
        "version": [
          {
            "Severity": "error",
            "Title": "Plugin version 0.0.9 is invalid.",
            "Detail": "The submitted plugin version 0.0.9 is not greater than the latest published version 0.0.9 on grafana.com.",
            "Name": "wrong-plugin-version"
          }
        ]
      }
    }

    Severity

    By default, the tool will show any warning or error level results from the analyzers. To see all results including successes, you can pass a configuration file which includes:

    global:
      reportAll: true

    Getting Help

    License

    Grafana Plugin Validator is distributed under the Apache 2.0 License.