Skip to content

Choose a tag to compare

@nvuillam nvuillam released this 05 Sep 13:24
· 6 commits to main since this release

What's Changed

  • Core

    • MegaLinter now prints a crash traceback when it is killed by a fatal signal (SIGSEGV, SIGBUS…), instead of exiting silently with no clue about what happened (#8779)
    • The LLM Advisor supports a new provider, OrcaRouter, an OpenAI-compatible AI gateway: set LLM_PROVIDER: orcarouter and ORCAROUTER_API_KEY in your environment to get fix suggestions routed through OrcaRouter (see the OrcaRouter provider page) (#8826)
  • New linters

    • biome, one fast toolchain linting, formatting and sorting imports of JavaScript, TypeScript, JSX, TSX, JSON, CSS and GraphQL files, available as JAVASCRIPT_BIOME, TYPESCRIPT_BIOME, JSX_BIOME, TSX_BIOME, JSON_BIOME, CSS_BIOME and GRAPHQL_BIOME (#8706)
      • Activated only when a biome.json or biome.jsonc configuration file is found in the repository
      • Supports APPLY_FIXES (safe fixes with --write) and native SARIF output
      • EXCLUDED_DIRECTORIES are forwarded in project lint mode through a generated configuration extending the workspace one
    • ApexGuru, the AI-driven engine of Salesforce Code Analyzer, available as SALESFORCE_CODE_ANALYZER_APEXGURU (#8820)
      • Detects SOQL inefficiencies, critical anti-patterns and scalability hotspots in your .cls and .trigger files, with line-level highlights, severity ratings and suggested fixes
      • The analysis runs in a connected Salesforce org, not locally: store the auth url of the target org in a CI secret named SFDX_AUTH_URL, and MegaLinter logs in to that org before the scan
      • The scan is sent to that org explicitly, so a .sfdx/sfdx-config.json left at the root of the repository, usually naming a long gone scratch org, can not hijack it
      • Inactive by default: it activates only when SFDX_AUTH_URL is defined, so nothing changes for existing Salesforce projects
      • Requires ApexGuru to be enabled on the org: it needs Scale Center, and is available for Unlimited Edition production orgs, full copy sandboxes, Signature orgs and Scale Test customers
      • A run where the engine could not analyze anything is reported as an error rather than a silent success, together with the reason and how to fix it
      • Supports native SARIF output, like the other Code Analyzer engines
    • tofu fmt, the built-in formatter of OpenTofu (the MPL-2.0 licensed fork of Terraform), available as TERRAFORM_TOFU_FMT (#8729)
      • Analyzes .tofu files only, the OpenTofu specific extension, so it never doubles up with TERRAFORM_TERRAFORM_FMT which keeps .tf
      • To format your .tf files with OpenTofu instead, set TERRAFORM_TOFU_FMT_FILE_EXTENSIONS: [".tofu", ".tf", ".tfvars"] and DISABLE_LINTERS: [TERRAFORM_TERRAFORM_FMT]
      • Supports APPLY_FIXES to rewrite files in the canonical OpenTofu style
    • tofu validate, the built-in validator of OpenTofu, available as TERRAFORM_TOFU_VALIDATE (#8793)
      • Reports what formatters and rule-based linters can not see: unsupported or missing arguments, wrong attribute types, references to undeclared variables, locals or outputs, and broken module input contracts
      • Analyzes .tofu files only, like TERRAFORM_TOFU_FMT, leaving .tf free for a future terraform validate linter. To validate .tf files, set TERRAFORM_TOFU_VALIDATE_FILE_EXTENSIONS: [".tofu", ".tf"]
      • Validates one whole module per directory, so every .tf and .tofu file of a selected directory is parsed and can produce diagnostics
      • Every directory is initialized with tofu init -backend=false beforehand, so no state is read, no state lock is taken and no cloud credentials are needed
      • Set TERRAFORM_TOFU_VALIDATE_INIT_ARGUMENTS to change those initialization arguments, for example adding -lockfile=readonly to have an out-of-sync .terraform.lock.hcl reported as an error instead of being updated
  • Disabled linters

    • COFFEE_COFFEELINT is disabled: CoffeeScript tooling is discontinued, and coffeelint can not receive EXCLUDED_DIRECTORIES in project lint mode (it has no exclusion option and reads .coffeelintignore only from its working directory). The linter will be removed in a future version (#8720)
    • GRAPHQL_GRAPHQL_SCHEMA_LINTER is disabled: graphql-schema-linter is unmaintained, with no release or commit since May 2022, and its peer dependency range pins graphql to ^15 || ^16, which held the whole GraphQL install back from graphql v17. Use GRAPHQL_BIOME to lint your GraphQL files. The linter will be removed in a future version (#8894)
  • Re-enabled linters

    • spectral is back as API_SPECTRAL, together with the API descriptor, to lint your OpenAPI, AsyncAPI and Arazzo specifications (#8717)
      • It was removed in v10.0.0 because it crashed at startup on every run: the cause has been found and fixed
      • Nothing to change in your configuration: API_SPECTRAL works again in ENABLE_LINTERS / DISABLE_LINTERS, and the default ruleset file is still .spectral.yaml
  • Linters enhancements

    • TERRAFORM_TFLINT now documents the tflint native GITHUB_TOKEN_github_com variable to authenticate plugin downloads on github.com, which is the recommended way to fix tflint --init failures when your GITHUB_TOKEN targets a GitHub Enterprise instance (#8795)
      • Set your github.com token in GITHUB_TOKEN_github_com, then list it in TERRAFORM_TFLINT_UNSECURED_ENV_VARIABLES: tflint gives it priority over GITHUB_TOKEN, which other linters and reporters keep using
      • PAT_GITHUB_COM is deprecated: it still works and now logs a warning, and will be removed in a future major release
    • CLOJURE_CLJSTYLE now forwards EXCLUDED_DIRECTORIES through its native repeatable --ignore argument, instead of a temporary .cljstyle written in your repository. Exclusions are now also applied when your repository already has a .cljstyle config, whose own ignore patterns are preserved (#8720)
    • SQL_SQLFLUFF does not receive EXCLUDED_DIRECTORIES in project lint mode anymore: sqlfluff reads path exclusions only from a .sqlfluffignore, .sqlfluff or pyproject.toml located inside the analyzed sources, where MegaLinter used to write a temporary file. List the directories to skip in your own .sqlfluffignore, or keep the default list_of_files lint mode where MegaLinter filters the files itself (#8720)
    • SARIF output is now available for 13 more linters: zizmor, bicep_linter, cppcheck, clj-kondo, roslynator, htmlhint, protolint, sqlfluff, swiftlint, osv-scanner, trufflehog, jscpd and lintr. Enable it the same way as any other SARIF-capable linter, with SARIF_REPORTER: true (optionally scoped with SARIF_REPORTER_LINTERS) (#8715)
      • The 4 Salesforce Code Analyzer engines (SALESFORCE_CODE_ANALYZER_APEX, _AURA, _LWC, _FLOW) also gained SARIF output: their report switches from CSV to SARIF automatically when SARIF reporting is requested
      • csharp_roslynator is bumped from 0.12.0 to 0.13.0, the first release including its SARIF output support
      • clj-kondo's upstream SARIF output currently nests the region property one level too deep, which may affect line/column display in strict SARIF consumers (clj-kondo/clj-kondo#2345)
    • Prettier linters (JSON_PRETTIER, YAML_PRETTIER, JAVASCRIPT_PRETTIER, TYPESCRIPT_PRETTIER) now tell you how to install a Prettier plugin when one declared in your .prettierrc fails to load with Cannot find package ... imported from noop.js (#6980)
      • Prettier v3 resolves plugins with a native ESM import() from the workspace and ignores NODE_PATH, so plugins installed with the default cwd: root land in /node-deps where Prettier never looks for them
      • The guidance surfaced in the log is to install them through <LINTER_KEY>_PRE_COMMANDS with cwd: workspace, which keeps plain package names in .prettierrc so the very same config still works when you run Prettier locally without MegaLinter
  • Fixes

    • MegaLinter does not crash anymore with This module only works with the 'fork' start method right after Processing linters on [N] parallel cores, which made every v10.0.0 run fail unless PARALLEL: false was set (#8808)
      • The PARALLEL: false workaround is not needed anymore, on the main image as well as on custom flavors
      • Messages logged by linters running in parallel are back in the console and in megalinter.log, including the extra output of LOG_LEVEL: DEBUG
    • PAT_GITHUB_COM is now hidden from the linters commands, like every other credential variable (#8795)
      • The GitHub Personal Access Token used by TERRAFORM_TFLINT was sent in cleartext to every linter, as it matched no pattern of SECURED_ENV_VARIABLES_DEFAULT
      • The default list now hides any variable named PAT, PAT_* or *_PAT (PAT_GITHUB_COM, AZURE_PAT...), and tflint --init still receives the real token
      • Add such a variable to <LINTER_KEY>_UNSECURED_ENV_VARIABLES if one of your linters really needs to read it
    • Fixed random Segmentation fault crashes of MegaLinter itself, which stopped the whole run with no error message (#8733). MegaLinter threads now get a full-size stack instead of the 128 KiB default of the Alpine images
    • Fixed leaked git processes when APPLY_FIXES is active: one was left behind by every fixer linter, which could exhaust the available file descriptors on long runs (#8779)
    • Fixed random crashes of project-mode linters (REPOSITORY_TRIVY, REPOSITORY_GRYPE, REPOSITORY_SYFT…) caused by MegaLinter writing temporary ignore files inside the analyzed sources: a file appearing then disappearing while another linter walked the repository aborted its scan (walk dir error: ... no such file or directory). MegaLinter now writes only in REPORT_OUTPUT_FOLDER, never in your sources (#8720)
    • EXCLUDED_DIRECTORIES and ADDITIONAL_EXCLUDED_DIRECTORIES are now forwarded to project lint mode linters even when the directory is nested, not only when it sits at the root of your repository (#8806)
      • A directory like infrastructure/cdk.out was previously scanned anyway, for example by REPOSITORY_BETTERLEAKS, which reported findings in generated files
      • Excluded entries are now looked up the same way MegaLinter filters files: by directory name, at any nesting level
      • Nothing changes when the excluded directory does not exist in your repository: it is still not sent to the linters
      • This also covers PYTHON_BANDIT, YAML_V8R, CSHARP_DOTNET_FORMAT, VBDOTNET_DOTNET_FORMAT and REPOSITORY_LS_LINT, whose exclusions are anchored on the repository root: they now receive the path of each nested directory found
      • A ^-anchored FILTER_REGEX_EXCLUDE keeps excluding root-level directories only: ^docs/ does not silence findings in packages/a/docs anymore
      • Looking up the excluded directories never descends into an excluded directory, and costs no extra repository scan: it reuses the one MegaLinter already does to list your files, and falls back to a single scan when only changed files are analyzed
    • REPOSITORY_TRUFFLEHOG does not silently skip findings anymore in a directory whose name merely ends with an excluded one: with dist excluded, secrets in my-dist/ were not reported (#8811)
    • REPORT_OUTPUT_FOLDER is now always excluded from what linters analyze, even when you override EXCLUDED_DIRECTORIES, and even when the folder does not exist yet when a linter starts (#8720)
    • The API reporter variables (API_REPORTER, API_REPORTER_URL…) are not flagged as deprecated anymore in the configuration JSON schema: they were collateral damage of the removal of the API descriptor in v10.0.0, and IDEs displayed them as obsolete (#8718)
    • REPOSITORY_BETTERLEAKS does not crash the whole MegaLinter run anymore when REPOSITORY_BETTERLEAKS_PR_COMMITS_SCAN: true is used on Azure Pipelines with the default shallow checkout (#8732)
      • The target branch commit is now searched across several reference spellings, so a branch available only locally is found too
      • When the Pull Request commit range can not be determined — on any platform — betterleaks now logs a warning explaining how to fix your checkout and scans the whole repository, instead of aborting the run
      • The Pull Request scan setup documentation lost when gitleaks was replaced by betterleaks is restored on the betterleaks page: checkout depth for each platform, Azure Pipelines variables to forward to the container, and how to compute the SHAs yourself (#8731)
    • The REPOSITORY_BETTERLEAKS Pull Request scan variables (REPOSITORY_BETTERLEAKS_PR_COMMITS_SCAN, REPOSITORY_BETTERLEAKS_PR_SOURCE_SHA, REPOSITORY_BETTERLEAKS_PR_TARGET_SHA) are now declared in the configuration JSON schema, so your IDE stops flagging them as unknown keys in .mega-linter.yml (#8805)
    • Bitbucket Pipelines is now recognized as a Pull Request context: PULL_REQUEST optimizations that were silently skipped there are applied again (#8780)
      • REPOSITORY_CHECKOV and REPOSITORY_BETTERLEAKS only analyze the Pull Request changes when asked to
      • Set BITBUCKET_PR_ID in your pipeline (Bitbucket provides it on Pull Request builds) to benefit from it
    • A run where all linters pass does not exit with an error anymore when MegaLinter can not list the files updated by the linters (#8649)
      • Happens on a read-only workspace whose repository uses git-lfs: the required LFS filter has nowhere to write its temporary files, so the git diff used to detect updated files exits 128
      • MegaLinter now logs a warning naming the workspace and the failed command, reports no updated source file, and completes the run. The UPDATED_SOURCES_REPORTER: false workaround is not needed anymore
    • REPOSITORY_CHECKOV does not fail anymore with argument -f/--file: expected at least one argument in a Pull Request where no file has been updated (#8802)
      • With VALIDATE_ALL_CODEBASE: false, checkov is now skipped when the Pull Request contains no updated file, instead of scanning the whole project or building an invalid command
      • Any linter using the list_of_files lint mode with no file to analyze is skipped the same way, instead of being called with an empty list of files
  • Reporters

    • Linters reporting in SARIF format no longer show No output available in Pull Request comments and summaries: the details section now names the SARIF report to open and links the MegaLinter artifacts (#8730)
      • Applies to the GitHub, GitLab, Azure and Bitbucket comment reporters and to the markdown summary
      • The link points where the reporter already links its detailed reports, so it follows REPORTERS_ACTION_RUN_URL when you set it
  • Doc

    • Comments are back at the bottom of every documentation page, powered by Giscus and backed by MegaLinter GitHub Discussions: ask a question or share a tip right from the page it applies to. The previous utteranc.es widget had silently stopped rendering
    • megalinter.io gets a dark mode: use the toggle in the header, or let it follow your system preference (#8848)
    • Refreshed look and feel, aligned with the OX Security brand: navy, indigo and lime replace the previous purple palette, and the Satoshi typeface is now actually loaded (it was silently falling back to the default font) (#8848)
    • New Docker pulls per month graph, showing the growth of MegaLinter adoption since October 2020, displayed in the README and on the Flavors statistics page (#8698)
    • Refreshed the MegaLinter references in linters documentation (linter_megalinter_ref_url): verified all existing links, updated moved pages (ktlint, robocop, csharpier, zizmor, ruff, proselint), and opened 47 suggestion PRs on linters repositories that did not mention MegaLinter yet (#8701, #8777)
    • New Security linting with ESLint section in the JAVASCRIPT_ES and TYPESCRIPT_ES documentation: states that no security plugin is bundled, shows the PRE_COMMANDS recipe and the createRequire reference needed under flat config, and lists commonly used plugins. Closes the gap left by the "Security Issues (with security plugins)" line, which previously named no plugin and had no working example (#8712)
  • mega-linter-runner

    • Node.js 22 or higher is now required (was 20) (#8710)
    • 8 npm dependencies removed (chalk, fs-extra, which, uuid, find-package-json, simple-git, mem-fs, assert), replaced by Node.js built-in modules: faster npx mega-linter-runner startup and a smaller supply-chain attack surface (#8710)
    • Fixed mega-linter-runner --version displaying error instead of the version when the npm_package_version environment variable is not set (#8710)
  • Agent Skills

    • The MegaLinter agent plugin now ships its three sub-agents to GitHub Copilot clients (VS Code, Copilot CLI, the Copilot app) (#8821)
      • Agent Plugins 1.0 standardizes skills but not sub-agents, so Copilot loads them from com.github.copilot/agents: the plugin now carries them there, generated from the Claude Code definitions so the two can not drift
      • megalinter-setup installs them correctly outside the plugin too: on Copilot the file name must end with .agent.md in .github/agents/, and the model: haiku override must be dropped
      • The skills stop guessing how they were installed from the skill naming, which only some platforms namespace: the install mode is now read from the filesystem, and you are asked when it stays ambiguous
      • The licence frontmatter key of the four skills is corrected to license, the spelling agents actually read
    • megalinter-check now handles the commit MegaLinter pushes itself when the repository uses APPLY_FIXES_MODE: commit (#8713)
      • CI providers ignore pushes made with the CI token, so the branch used to stay stuck on the stale checks of the run that produced the fixes
      • The commit is amended with a 🤖 prefix and re-pushed with --force-with-lease, which re-triggers the checks (you are asked first on the default branch)
      • Nothing is amended when another commit landed after the auto-fix one, when it was already amended, or when you have local commits left to push — a normal push already re-triggers the checks in those cases
    • megalinter-setup can now set up a custom flavor repository on request, from creating the repository to publishing and maintaining the image (#8713)
      • It first looks for a custom flavor you already own or administer, to reuse or extend it instead of maintaining a second one
    • megalinter-setup in upgrade mode now also updates the installed skills and sub-agents (npx skills update), so the guidance you run matches the MegaLinter version you just upgraded to (#8713)
    • The MegaLinter skills are now installable as an agent plugin, so one command brings the four skills and the three sub-agents at once, and keeps them updated (#8791)
      • Claude Code: /plugin marketplace add oxsecurity/megalinter then /plugin install megalinter@megalinter
      • Cursor, GitHub Copilot, Codex, Gemini CLI and Antigravity each have their own install command, listed on the Coding Agents (Plugins) page
      • The sub-agents ship with the plugin on Claude Code and Cursor; elsewhere the skills install alone and run inline
      • npx skills add oxsecurity/megalinter/skills keeps working for every other coding agent
  • Dev

    • REPOSITORY_TRUFFLEHOG tests no longer depend on a third-party endpoint. The good and bad fixtures differed only by a basic-auth credential that trufflehog validated over the network, so the whole test suite went red whenever the runner could not reach that site (#8848)
      • The fixtures now differ by what is detected, the good ones carrying no secret material at all, and the tests drop --only-verified, which stays the production default
      • The .wireit poison fixture gains a private key, so the excluded-directories forwarding guard actually fires instead of being vacuous
    • The documentation site is now built with Zensical, the successor of Material for MkDocs, replacing mkdocs, mkdocs-material and mkdocs-glightbox (#8848)
      • mkdocs.yml stays the configuration file, so .automation/build.py nav generation is unchanged; hatch run docs:serve and hatch run docs:build now call zensical
      • Versioned deploys still use mike, from the Zensical-compatible fork squidfunk/mike pinned to a commit SHA and watched by a new Renovate custom manager
      • The Check MkDocs generation workflow becomes Check documentation generation (test-docs.yml) and also runs on docs/** changes
      • Three long-dead pieces of documentation configuration were found and removed or fixed on the way: the disqus template block (Material has no such block, so comments never rendered), the Satoshi, sans-serif theme font (one quoted family name that matched nothing), and the h1[content~=Home] CSS rule (h1 has no content attribute)
    • Parallel linters logging does not depend on the multiprocessing start method anymore: init_worker() installs a QueueHandler on the worker root logger, built from the queue and the level passed by process_linters_parallel(), instead of relying on the handlers a forked worker inherits (#8808)
      • Python 3.14 changed the default start method on Linux from fork to forkserver: workers then started with no handler and the default WARNING level, so their records were lost or written directly to their own stdout, bypassing the queue listener and the log file
      • The AssertionError crash itself came from multiprocessing_logging.install_mp_handler(), which asserts the fork start method; the dependency was already dropped in this version
      • New parallel_logging_test.py runs a worker with every start method available on the platform and checks that its records reach the main process handlers
    • replacement_env_vars is now declared in the MegaLinter configuration JSON schema (command_info definition, with its var_src / var_dest items) and documented in the Pre-commands page: it was implemented but validated by nothing, as additionalProperties is unset (#8812)
      • pre_post_factory.build_command_env() extracts the child environment build from run_command(), and resolves var_src from the raw configuration instead of the already secured environment, so a secured source variable is not copied as HIDDEN_BY_MEGALINTER
    • Crash diagnostics: megalinter.run.enable_crash_diagnostics() enables faulthandler and raises the thread stack size to 8 MiB (the glibc default) before any thread is started, and worker processes enable faulthandler too. musl gives threads a 128 KiB stack and CPython below 3.14.7 miscomputed its stack guard there (cpython#148260), so C-level recursion in a thread - such as pickling the linter object graph in the multiprocessing.Pool handler threads, which reaches the whole Megalinter instance through Linter.master - crashed the process with SIGSEGV instead of raising RecursionError (#8779)
      • Verified on python:3.14.6-alpine: pickling a deeply nested object in a thread exits with signal 11, and either raising the thread stack size or moving to python:3.14.7-alpine turns it into a plain RecursionError
      • faulthandler can not report a stack overflow itself (the handler has no stack left to run on), which is why the crash in #8733 left no output at all; it does report every other fatal signal
    • The Docker images assert a Python 3.14.7 floor at build time, the first release carrying the CPython musl thread stack fixes. The python:3.14-alpine3.24 tag stays floating because renovate.json5 scopes the dockerfile manager away from the main Dockerfile, whose FROM lines are generated from descriptors (#8779)
    • Retired the cli_lint_mode_project_exclude_workspace_file_name descriptor property and the write_workspace_generated_file() helper, and removed the property from the descriptor JSON schema so a future descriptor can not silently reintroduce a write inside the analyzed sources. Exclusion forwarding now offers three mechanisms only: native CLI flag, generated ignore file in the report folder, generated config via manage_excluded_directories_config() (#8720)
    • Deprecation flags of removed linters are now reversible in the configuration JSON schema: build.py clears the deprecated flag and the (deprecated) title prefix of variables whose linter or descriptor is back, instead of only ever adding them (#8718)
    • New megalinter/ci_providers/ package, mirroring the api_providers pattern: CiProvider base class plus CiProviderAzurePipelines, CiProviderGithubActions and CiProviderGitlab, exposing get_pr_commit_shas() and a platform specific get_pr_commit_shas_hint() (#8780)
      • ci_providers.get_pr_ci_provider() returns the provider matching the current Pull Request context, falling back to the neutral base provider so callers never handle a missing provider
      • The Azure Pipelines and GitHub Pull Request SHA lookups moved out of BetterleaksLinter, which keeps only the orchestration, and are now covered by ci_providers_test.py outside Docker
    • CI platform knowledge is concentrated in megalinter/ci_providers/ instead of being spread across utils, utils_reporter, MegaLinter and the reporters (#8780)
      • reporters/jenkins_ci_vars.py becomes ci_providers/CiProviderJenkins.py: it was never a reporter, it is called from Megalinter.__init__
      • New CiProviderBitbucket, and every provider implements is_current(), so get_ci_provider() resolves the platform running the build
      • CiProvider exposes get_repo_name(), get_branch_name(), get_job_url(), log_section_start/end(), set_output(), publish_job_summary() and markdown_supports_html_details
      • utils.get_git_context_info() and utils_reporter.log_section_start/end() delegate to the provider instead of their platform if/elif chains, and the GitHub run URL (built in 3 places), the Bitbucket step URL (2 places) and the Azure BUILD_BUILDID/BUILD_BUILD_ID fallback are deduplicated
      • utils.is_ci() and utils.is_pr() were missing Bitbucket Pipelines; new utils.is_bitbucket_pr()
      • The comment reporters (GithubCommentReporter, GitlabCommentReporter, AzureCommentReporter, BitbucketCommentReporter) and GithubStatusReporter now get their repository, Pull Request number, tokens, API urls and headers from their provider instead of reading platform variables themselves; they keep only the comment transport and rendering
      • Each reporter instantiates its own platform provider directly rather than calling get_ci_provider(): under Jenkins the running platform is Jenkins, which maps its variables onto the other platforms', so a factory lookup would disable the comment reporters there
      • CiProviderAzurePipelines owns the repository id resolution (SYSTEM_PULLREQUEST_SOURCEREPOSITORYURI parsing, API lookup, BUILD_REPOSITORY_ID fallback) and build_git_api_url(); CiProviderGitlab owns the merge request iid resolution and the python-gitlab auth options
      • GitHub keeps get_auth_token() (GITHUB_TOKEN) and get_user_auth_token() (PAT) separate on purpose: commit statuses need the statuses:write scope that the documented fine-grained PAT does not carry
    • spectral is installed in its own node_modules tree (/node-deps-spectral) instead of the shared /node-deps one, which is what made it crash: @prantlf/jsonlint pins ajv to exactly 8.17.1 and so owns the hoisted root copy, while @stoplight/spectral-core requires ajv >= 8.18.0 and gets a nested one, so its hoisted ajv-errors bound to the other ajv instance and ajv generated invalid JavaScript (SyntaxError: Unexpected token ':' at new Function). Any npm linter sharing the tree with an exact-pinned transitive dependency can hit the same trap (#8718)
    • 6 Python dependencies removed from the MegaLinter runtime, replaced by standard library equivalents: commentjson, terminaltables and multiprocessing_logging (unmaintained), plus termcolor, regex and the obsolete importlib-metadata backport (#8710)
    • Shared linter definitions: linter entries duplicated across several descriptors (eslint, prettier, v8r, dotnet-format, cpplint, cppcheck, clang-format) are now factorized in megalinter/descriptors/shared/*.megalinter-linter.yml files, referenced from descriptors with the new linter-level extends property (shallow merge, descriptor entry properties override the shared ones) (#8705)
    • Docker pulls monthly chart: the auto-update workflow now regenerates docs/assets/images/docker-pulls-monthly.svg (new pulls per month since October 2020, all images and registries), via the new .automation/docker_pulls_chart.py called by build.py after the pull counters update (#8698)
      • Historical monthly points are frozen in .automation/generated/docker-pulls-monthly.json (built once from the tracked stats plus a Web Archive reconstruction of the collection gaps); the script only appends newly completed months computed from flavors-stats.json
    • Docker pull counters now also track the standalone megalinter-only-* images: their download counts are stored in flavors-stats.json and included in the README badge total (#8698)
    • New descriptor activation_rules type variable_is_set, activating a linter as soon as a variable holds a value. The existing variable type can only compare a variable to a fixed expected_value, which can not express "a credential is present" - the condition SALESFORCE_CODE_ANALYZER_APEXGURU needs on SFDX_AUTH_URL (#8820)
      • Linter tests gated on such a variable skip themselves when it is missing, instead of failing: LinterTestRoot.skip_if_required_variables_missing() guards the per-lint-mode and SARIF tests, while the version and help tests keep running since they need no credential
    • The release build stages newly generated documentation pages too: build.py staged only already-tracked files (git add -u), so a page created for the first time was left out of the release commit and 404ed on megalinter.io — as docs/licenses/rumdl.md and docs/licenses/zizmor.md still do since v10.0.0
  • CI

    • The generated linter guides in skills/megalinter-fix/linters/ are excluded from the markdown linters: their error-format regexes end with a significant space that markdownlint --fix strips, which corrupted the documented regex and left the working tree dirty, failing the auto-fix commit step on every pull request (#8848)
    • Supply-chain hardening of dependency updates: Renovate (minimumReleaseAge) and Dependabot (cooldown) now wait until a release is at least 7 days old before proposing an upgrade, so compromised releases can be caught by the community first. Security fixes are not delayed and still open immediately (#8710)
    • New Check agent plugins manifests workflow validating the agent plugin manifests on every change to them or to skills/: .automation/validate_agent_plugins.py checks the root plugin.json against the published Agent Plugins 1.0 schema and keeps the per-vendor manifests consistent with it, then claude plugin validate ./ --strict checks the Claude Code marketplace and plugin manifests (#8791)
    • The auto-update workflow patch-bumps the agent plugin version when it regenerates the skills: the plugin follows its own release train, since its fix guides change far more often than MegaLinter is released. plugin.json is the single source of truth, mirrored into the per-vendor manifests by .automation/agent_plugin_manifests.py (called by build.py) (#8791)
    • The test workflows forward the SFDX_AUTH_URL repository secret to the test container, so the SALESFORCE_CODE_ANALYZER_APEXGURU lint tests can reach a connected org. The secret is not exposed on pull requests from forked repositories, where those tests skip themselves (#8820)
    • The Auto-Update Linters workflow is fixed: entrypoint.sh still installed the MkDocs documentation stack, so build.sh aborted with zensical: command not found since the Zensical migration and no linter version update pull request could be created (#8901)
  • Linter versions upgrades (44)

Pull Requests
  • [automation] Auto-update linters version, help and documentation by @github-actions[bot] in #8697
  • Add auto-refreshed Docker pulls per month graph in README and documentation by @nvuillam in #8698
  • Refresh MegaLinter references in linter descriptors by @nvuillam in #8701
  • chore(deps): update dependency virtualenv to v21.7.3 by @renovate[bot] in #8700
  • chore(deps): update dependency djlint to v1.44.2 by @renovate[bot] in #8699
  • chore(deps): update mstruebing/editorconfig-checker docker tag to v3.11.1 by @renovate[bot] in #8702
  • chore(deps): update roslynator to 4.16.0 by @renovate[bot] in #8703
  • chore(deps): update dependency @eslint-react/eslint-plugin to v5.18.3 by @renovate[bot] in #8704
  • Factorize duplicated linter definitions with shared linter files and extends property by @nvuillam in #8705
  • Add biome linter for JavaScript, TypeScript, JSX, TSX, JSON, CSS and GraphQL by @nvuillam in #8706
  • [automation] Auto-update linters version, help and documentation by @github-actions[bot] in #8707
  • chore(deps): update dependency pylint to v4.0.7 by @renovate[bot] in #8708
  • Strengthen supply-chain security: remove replaceable dependencies and add 7-day update cooldowns by @nvuillam in #8710
  • Agent skills: handle MegaLinter auto-fix commits when watching CI, and set up custom flavor repositories by @nvuillam in #8713
  • [automation] Auto-update linters version, help and documentation by @github-actions[bot] in #8709
  • Fix typos discovered by codespell by @cclauss in #8714
  • [automation] Auto-update linters version, help and documentation by @github-actions[bot] in #8716
  • Restore API_SPECTRAL: fix the ajv conflict that made spectral crash by @nvuillam in #8718
  • docs(javascript,typescript): document ESLint security plugin usage by @ofri-peretz in #8712
  • Add SARIF output support for 13 linters + 4 Salesforce Code Analyzer engines by @nvuillam in #8715
  • Explain how to install Prettier plugins when they fail to resolve by @nvuillam in #8721
  • [automation] Auto-update linters version, help and documentation by @github-actions[bot] in #8719
  • Never write inside the analyzed sources: fix the random project-mode linter crashes by @nvuillam in #8720
  • [automation] Auto-update linters version, help and documentation by @github-actions[bot] in #8726
  • chore(deps): update dependency eslint to v10.8.1 by @renovate[bot] in #8723
  • chore(deps): update dependency eslint-plugin-n to v18.3.0 - autoclosed by @renovate[bot] in #8724
  • chore(deps): update dependency serialize-javascript to v7.1.0 by @renovate[bot] in #8725
  • chore(deps): update dependency @salesforce/plugin-packaging to v3.0.5 by @renovate[bot] in #8727
  • chore(deps): update dependency @salesforce/cli to v2.148.3 by @renovate[bot] in #8728
  • chore(deps): update dependency @biomejs/biome to v2.5.8 by @renovate[bot] in #8734
  • chore(deps): update dependency @eslint-react/eslint-plugin to v5.18.6 by @renovate[bot] in #8736
  • chore(deps): update dependency betterleaks/betterleaks to v1.7.4 by @renovate[bot] in #8737
  • chore(deps): update dependency aquasecurity/trivy to v0.74.0 - autoclosed by @renovate[bot] in #8738
  • chore(deps): update dependency mongodb/kingfisher to v1.113.0 by @renovate[bot] in #8739
  • chore(deps): update dependency pytest-rerunfailures to v16.5 by @renovate[bot] in #8740
  • chore(deps): update dependency robotframework-robocop to v8.8.0 by @renovate[bot] in #8741
  • chore(deps): update dependency semgrep to v1.173.0 by @renovate[bot] in #8742
  • chore(deps): update trufflesecurity/trufflehog docker tag to v3.97.0 by @renovate[bot] in #8743
  • chore(deps): update yoheimuta/protolint docker tag to v0.57.0 by @renovate[bot] in #8744
  • chore(deps): update dependency gitpython to v3.1.59 by @renovate[bot] in #8748
  • chore(deps): update dependency eslint-plugin-jest to v29.16.1 by @renovate[bot] in #8747
  • Build(deps): Bump uvicorn from 0.52.1 to 0.52.3 in /server by @dependabot[bot] in #8749
  • chore(deps): update typescript-eslint monorepo to v8.67.0 by @renovate[bot] in #8776
  • Build(deps): Bump langchain-core from 1.5.3 to 1.5.5 in /.config/python/dev by @dependabot[bot] in #8758
  • chore(deps): update dependency anchore/grype to v0.117.0 by @renovate[bot] in #8769
  • Build(deps): Bump langchain-google-genai from 4.3.2 to 4.3.4 in /.config/python/dev by @dependabot[bot] in #8756
  • chore(deps): update dependency npm-package-json-lint to v10.5.1 by @renovate[bot] in #8774
  • chore(deps): update dependency cfn-lint to v1.55.1 by @renovate[bot] in #8772
  • chore(deps): update dependency orjson to v3.12.0 by @renovate[bot] in #8775
  • chore(deps): update dependency uvicorn to v0.52.3 by @renovate[bot] in #8766
  • Build(deps): Bump langchain-openai from 1.4.2 to 1.5.1 in /.config/python/dev by @dependabot[bot] in #8753
  • Update MegaLinter reference URLs after suggestion PRs outcome by @nvuillam in #8777
  • [automation] Auto-update linters version, help and documentation by @github-actions[bot] in #8735
  • Fix random Segmentation fault crashes on Alpine images (#8733) by @nvuillam in #8779
  • Fix betterleaks PR scan crash on Azure Pipelines, and gather CI platform logic in ci_providers by @nvuillam in #8780
  • [automation] Auto-update linters version, help and documentation by @github-actions[bot] in #8778
  • chore(deps): update dependency powershell/powershell to v7.6.5 by @renovate[bot] in #8762
  • chore(deps): update dependency langchain_anthropic to v1.5.6 by @renovate[bot] in #8768
  • chore(deps): update dependency virtualenv to v21.7.4 by @renovate[bot] in #8767
  • chore(deps): update dependency rumdl to v0.2.55 by @renovate[bot] in #8765
  • chore(deps): update dependency pyright to v1.1.413 by @renovate[bot] in #8763
  • chore(deps): update dependency open to v11.0.1 by @renovate[bot] in #8761
  • chore(deps): update dependency jscpd to v5.0.15 by @renovate[bot] in #8760
  • Build(deps): Bump langchain-anthropic from 1.5.4 to 1.5.6 in /.config/python/dev by @dependabot[bot] in #8755
  • [automation] Auto-update linters version, help and documentation by @github-actions[bot] in #8783
  • Add tofu fmt (OpenTofu) as TERRAFORM_TOFU_FMT by @nvuillam in #8782
  • chore(deps): update dependency ruff to v0.16.3 by @renovate[bot] in #8764
  • chore(deps): update dependency anchore/syft to v1.51.0 by @renovate[bot] in #8770
  • chore(deps): update dependency ansible-lint to v26.8.0 by @renovate[bot] in #8771
  • chore(deps): update dependency langsmith to v0.11.0 by @renovate[bot] in #8787
  • chore(deps): update dependency rubocop-rails to v2.37.0 by @renovate[bot] in #8789
  • chore(deps): update dependency ip-address to v10.5.0 by @renovate[bot] in #8773
  • chore(deps): update dependency checkov to v3.3.11 by @renovate[bot] in #8785
  • chore(deps): update dependency rubocop-performance to v1.27.0 by @renovate[bot] in #8788
  • Publish the MegaLinter skills as agent plugins by @nvuillam in #8791
  • [automation] Auto-update linters version, help and documentation by @github-actions[bot] in #8784
  • Point at the SARIF report instead of "No output available" in reporters by @nvuillam in #8781
  • chore(deps): update dependency jscpd to v5.0.16 by @renovate[bot] in #8800
  • chore(deps): update dependency @biomejs/biome to v2.5.9 by @renovate[bot] in #8799
  • fix(deps): update dependency langchain-openai to ~=1.5.2 by @renovate[bot] in #8745
  • Update schema generator for Betterleaks by @wesley-dean in #8805
  • [automation] Auto-update linters version, help and documentation by @github-actions[bot] in #8804
  • Keep a green run green when git cannot list updated files by @trevor-vaughan in #8796
  • Fix parallel run crash and lost linter logs with the Python 3.14 multiprocessing start method by @nvuillam in #8810
  • Add tofu validate (OpenTofu) as TERRAFORM_TOFU_VALIDATE by @eloyred in #8794
  • Never build a lint command with an empty list of files by @nvuillam in #8809
  • chore(deps): update dependency rumdl to v0.2.57 by @renovate[bot] in #8803
  • [automation] Auto-update linters version, help and documentation by @github-actions[bot] in #8815
  • Ship the agent plugin sub-agents to GitHub Copilot clients by @nvuillam in #8821
  • Build(deps): Bump the npm_and_yarn group across 2 directories with 6 updates by @dependabot[bot] in #8818
  • Secure PAT_GITHUB_COM and document tflint native host-specific token by @nvuillam in #8812
  • chore(deps): update dependency ruff to v0.16.4 by @renovate[bot] in #8817
  • chore(deps): update dependency @salesforce/plugin-packaging to v3.0.6 by @renovate[bot] in #8822
  • chore(deps): update langchain (patch) by @renovate[bot] in #8819
  • chore(deps): update dependency friendsofphp/php-cs-fixer to v3.95.21 by @renovate[bot] in #8827
  • chore(deps): update dependency checkov to v3.3.13 by @renovate[bot] in #8825
  • chore(deps): update dependency langsmith to v0.11.1 by @renovate[bot] in #8828
  • chore(deps): update dependency @biomejs/biome to v2.5.10 by @renovate[bot] in #8824
  • Build(deps): Bump langchain-anthropic from 1.5.6 to 1.6.1 in /.config/python/dev by @dependabot[bot] in #8834
  • Build(deps): Bump pygithub from 2.9.1 to 2.10.0 in /.config/python/dev by @dependabot[bot] in #8841
  • Build(deps): Bump langchain-openai from 1.5.2 to 1.6.0 in /.config/python/dev by @dependabot[bot] in #8840
  • chore(deps): update dependency rumdl to v0.2.60 by @renovate[bot] in #8842
  • chore(deps): update dependency phpstan/phpstan to v2.2.9 by @renovate[bot] in #8829
  • chore(deps): update dependency realm/swiftlint to v0.65.1 by @renovate[bot] in #8830
  • Build(deps): Bump docker/setup-buildx-action from 4.2.0 to 4.3.0 by @dependabot[bot] in #8831
  • Build(deps): Bump pygments from 2.20.0 to 2.21.0 in /server by @dependabot[bot] in #8832
  • Build(deps): Bump rq from 2.10.0 to 2.11.0 in /server by @dependabot[bot] in #8833
  • Build(deps): Bump pytest-rerunfailures from 16.5 to 16.6 in /.config/python/dev by @dependabot[bot] in #8836
  • Build(deps): Bump langchain-core from 1.5.6 to 1.6.0 in /.config/python/dev by @dependabot[bot] in #8838
  • chore(deps): update dependency pymdown-extensions to v11.0.2 by @renovate[bot] in #8843
  • Build(deps): Bump idna from 3.18 to 3.19 in /server by @dependabot[bot] in #8835
  • Build(deps): Bump idna from 3.18 to 3.19 in /.config/python/dev by @dependabot[bot] in #8839
  • Build(deps): Bump uvicorn from 0.52.3 to 0.52.4 in /server by @dependabot[bot] in #8837
  • Forward nested excluded directories to project mode linters by @nvuillam in #8811
  • feat: add OrcaRouter as an LLM Advisor provider by @zsanig22-dotcom in #8826
  • [automation] Auto-update linters version, help and documentation by @github-actions[bot] in #8823
  • Migrate documentation build from MkDocs to Zensical by @nvuillam in #8848
  • chore(deps): update dependency snakemake to v9.25.2 by @renovate[bot] in #8847
  • chore(deps): update dependency skaji/cpm to v1.1.5 - autoclosed by @renovate[bot] in #8846
  • chore(deps): update dependency friendsofphp/php-cs-fixer to v3.95.22 by @renovate[bot] in #8845
  • chore(deps): update redis docker tag to v8.10.1 by @renovate[bot] in #8850
  • chore(deps): update dependency eslint to v10.9.1 by @renovate[bot] in #8849
  • chore(deps): update alpine/terragrunt docker tag to v1.15.9 - autoclosed by @renovate[bot] in #8844
  • chore(deps): update roslynator to 4.16.1 by @renovate[bot] in #8853
  • chore(deps): update dependency cspell to v10.1.1 by @renovate[bot] in #8859
  • chore(deps): update dependency betterleaks/betterleaks to v1.8.1 by @renovate[bot] in #8856
  • chore(deps): update trufflesecurity/trufflehog docker tag to v3.97.1 by @renovate[bot] in #8855
  • chore(deps): update dependency virtualenv to v21.7.5 by @renovate[bot] in #8854
  • chore(deps): update dependency gitpython to v3.1.60 by @renovate[bot] in #8862
  • chore(deps): update npm-package-json-lint to v11 and its config-default to v10 by @nvuillam in #8860
  • chore(deps): update dependency eslint-plugin-jest to v29.16.2 by @renovate[bot] in #8861
  • Add ApexGuru engine of Salesforce Code Analyzer (SALESFORCE_CODE_ANALYZER_APEXGURU) by @nvuillam in #8820
  • chore(deps): update dependency sfdx-hardis to v8 by @renovate[bot] in #8880
  • chore(deps): update dependency @biomejs/biome to v2.5.11 by @renovate[bot] in #8858
  • chore(deps): update mstruebing/editorconfig-checker docker tag to v3.11.2 by @renovate[bot] in #8863
  • chore(deps): update dependency eslint to v10.9.1 by @renovate[bot] in #8864
  • chore(deps): update dependency @salesforce/plugin-packaging to v3.0.6 by @renovate[bot] in #8867
  • chore(deps): update dependency anchore/syft to v1.51.1 by @renovate[bot] in #8868
  • chore(deps): update dependency eslint-plugin-jest to v29.16.5 by @renovate[bot] in #8869
  • chore(deps): update dependency pygments to v2.21.0 by @renovate[bot] in #8870
  • chore(deps): update dependency rubocop to v1.90.0 by @renovate[bot] in #8871
  • chore(deps): update dependency rust-lang/rust to v1.98.0 by @renovate[bot] in #8872
  • chore(deps): update dependency semgrep to v1.175.0 by @renovate[bot] in #8873
  • chore(deps): update dependency yeoman-environment to v6.2.0 by @renovate[bot] in #8874
  • chore(deps): update dependency yeoman-generator to v8.3.0 by @renovate[bot] in #8875
  • chore(deps): update salesforce packages (minor) by @renovate[bot] in #8876
  • chore(deps): update typescript-eslint monorepo to v8.68.0 by @renovate[bot] in #8877
  • chore(deps): update dependency mongodb/kingfisher to v2 by @renovate[bot] in #8879
  • chore(deps): update dependency checkov to v3.3.15 by @renovate[bot] in #8882
  • chore(deps): update dependency friendsofphp/php-cs-fixer to v3.95.23 by @renovate[bot] in #8883
  • chore(deps): update dependency ruff to v0.16.5 by @renovate[bot] in #8884
  • chore(deps): update dependency rumdl to v0.2.62 by @renovate[bot] in #8885
  • chore(deps): update langchain (patch) by @renovate[bot] in #8886
  • chore(deps): update secretlint monorepo to v13.0.5 by @renovate[bot] in #8887
  • chore(deps): update dependency click to v8.5.0 by @renovate[bot] in #8888
  • chore(deps): update dependency snakemake to v9.26.0 by @renovate[bot] in #8889
  • chore(deps): update jdkato/vale docker tag to v3.18.0 by @renovate[bot] in #8890
  • chore(deps): update dependency isort to v9 by @renovate[bot] in #8891
  • chore(deps): update dependency robotframework-robocop to v9 by @renovate[bot] in #8892
  • chore(deps): update dependency @eslint-react/eslint-plugin to v5.18.7 by @renovate[bot] in #8866
  • chore(deps): update dependency anchore/grype to v0.118.0 by @renovate[bot] in #8898
  • chore(deps): update dependency golangci/golangci-lint to v2.13.2 by @renovate[bot] in #8895
  • chore(deps): update dependency langsmith to v0.11.2 by @renovate[bot] in #8896
  • chore(deps): update dependency snakemake to v9.26.1 by @renovate[bot] in #8897
  • Disable the unmaintained graphql-schema-linter by @nvuillam in #8894
  • fix(renovate-rebase): force UTF-8 console output in tick_dashboard by @nvuillam in #8900
  • fix(deps): update langchain (minor) by @renovate[bot] in #8878
  • fix(ci): install zensical in the auto-update linters container by @nvuillam in #8901
  • [automation] Auto-update linters version, help and documentation by @github-actions[bot] in #8902

New Contributors

MegaLinter is provided by OX Security

⭐ If MegaLinter is useful to you, please give it a star on GitHub — it helps the project a lot!

Full Changelog: v10.0.0...v10.1.0