Skip to content

feat(linode): add provider with administration compute and networking services#11633

Open
varunmamillapalli wants to merge 30 commits into
prowler-cloud:masterfrom
varunmamillapalli:feat/linode-provider
Open

feat(linode): add provider with administration compute and networking services#11633
varunmamillapalli wants to merge 30 commits into
prowler-cloud:masterfrom
varunmamillapalli:feat/linode-provider

Conversation

@varunmamillapalli

@varunmamillapalli varunmamillapalli commented Jun 17, 2026

Copy link
Copy Markdown

Context

This PR introduces the Linode provider to Prowler, enabling security assessments for Linode-managed infrastructure as described in #11504.

Description

Adds Linode provider infrastructure with CLI integration (no API/UI) using Linode's official Python SDK. Support is added for 3 Linode product-area services — administration, compute, and networking — with 10 checks across 4 security categories.

Authentication is handled exclusively through the LINODE_TOKEN environment variable. The token currently needs read-only access to account, firewalls, and Linodes.

  • Authentication is supported through LINODE_TOKEN.
  • Mutelist support is implemented.
  • Documentation is provided for authentication and getting started.
  • Unit tests cover provider, services, checks, CLI discovery, outputs, and metadata validation.

Services

Service Coverage
administration Account users and identity/access checks
compute Linode instances
networking Cloud Firewalls

List of checks

Check Description
administration_user_2fa_enabled Ensures account users have two-factor authentication enabled
compute_instance_backups_enabled Ensures a Linode instance has backups enabled
compute_instance_disk_encryption_enabled Ensures a Linode instance has disk encryption enabled
compute_instance_watchdog_enabled Ensures a Linode instance has Watchdog (Lassie) enabled
networking_firewall_assigned_to_devices Verifies if a Cloud Firewall is attached to devices
networking_firewall_default_inbound_policy_drop Validates if the default inbound policy for a Cloud Firewall is set to DROP
networking_firewall_default_outbound_policy_drop Validates if the default outbound policy for a Cloud Firewall is set to DROP
networking_firewall_inbound_rules_configured Checks if a Cloud Firewall has inbound rules configured
networking_firewall_outbound_rules_configured Checks if a Cloud Firewall has outbound rules configured
networking_firewall_status_enabled Checks if a Cloud Firewall is enabled

Screenshots of running various scans

All these runs have LINODE_TOKEN set in the environment:

  1. Running a full scan with 2 Linode instances and 2 firewalls - prowler linode --verbose
📸 View Full Scan Screenshots (4)
full-scan-1 full-scan-2 full-scan-3 full-scan-4
  1. Scan for just the networking service with both firewalls disabled - prowler linode --services networking --verbose
📸 View Networking Service Scan Screenshots (3)
fw-svc-scan-1 fw-svc-scan-2 fw-svc-scan-3
  1. Scan for a single compute check with Watchdog enabled - prowler linode --checks compute_instance_watchdog_enabled --verbose
📸 View Watchdog Compute Check Scan Screenshot (1)
inst-check-scan
  1. All output files are correctly generated:
📸 View Output Folder Screenshot (1)
output-files

Steps to review

  • Review provider infrastructure in prowler/providers/linode/
  • Review Linode services in prowler/providers/linode/services/administration/, compute/, and networking/
  • Review authentication and getting-started documentation in docs/user-guide/providers/linode/
  • Test locally:
# Unit tests
pytest -n auto -vvv -s -x tests/providers/linode

# With LINODE_TOKEN set
prowler -h # Should list Linode in the available cloud providers list

prowler linode --list-services # Should list administration, compute, and networking

prowler linode --list-checks # Should list all 10 available checks

prowler linode --list-categories # Should list the associated categories for the checks

prowler linode --verbose # Should run a scan against the Linode account and create report files in the output directory

Checklist

Community Checklist

SDK/CLI

  • Are there new checks included in this PR? Yes
    • If so, do we need to update permissions for the provider? Please review this carefully.

License

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

@varunmamillapalli varunmamillapalli requested review from a team as code owners June 17, 2026 16:55
@github-actions github-actions Bot added documentation output/html Issues/PRs related with the HTML output format compliance Issues/PRs related with the Compliance Frameworks metadata-review community Opened by the Community labels Jun 17, 2026
@coderabbitai

coderabbitai Bot commented Jun 17, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds Linode as a new Prowler cloud provider with PAT-based authentication, three service modules (account, firewall, instance), eight security checks across two services, mutelist support, integrated CLI/output/HTML reporting, Pydantic models, custom exception hierarchy, comprehensive unit tests, user-facing documentation, and CI integration.

Changes

Linode Provider Integration

Layer / File(s) Summary
Core contracts: models, exceptions, and check report type
prowler/config/config.py, prowler/providers/linode/models.py, prowler/providers/linode/exceptions/exceptions.py, prowler/lib/check/models.py
Provider enum gains LINODE member, Pydantic models LinodeSession, LinodeIdentityInfo, and LinodeOutputOptions are introduced, a four-class exception hierarchy (LinodeCredentialsError code 18000, LinodeAuthenticationError 18001, LinodeSessionError 18002, LinodeIdentityError 18003) extending LinodeBaseException is added, and CheckReportLinode dataclass is defined with resource_name, resource_id, and region fields.
LinodeProvider: initialization, credentials, and connection validation
prowler/providers/linode/linode_provider.py, prowler/providers/common/provider.py
LinodeProvider is implemented with __init__ (config/mutelist loading and session setup), setup_session (token resolution from argument or LINODE_TOKEN env), setup_identity (fetching username/email/account_id from API with per-field fallbacks), print_credentials (colorized credential report), test_connection (API validation), and all read-only properties; Provider.init_global_provider gains a linode dispatch branch.
CLI parser, arguments, and discovery registration
prowler/lib/cli/parser.py, prowler/providers/linode/lib/arguments/arguments.py
linode is added to known_providers set and epilog usage text for CLI help; --linode-token argument subcommand is registered via init_parser.
Output option routing and finding/report rendering
prowler/__main__.py, prowler/lib/outputs/finding.py, prowler/lib/outputs/html/html.py, prowler/lib/outputs/outputs.py, prowler/lib/outputs/summary_table.py
LinodeOutputOptions is wired into __main__ output selection; Linode branches are added to Finding.generate_output (auth_method, account_uid with fallback chain), HTML.get_linode_assessment_summary (credential summary card), stdout_report (region detail), and display_summary_table (Account entity label).
LinodeService base class with concurrent execution and mutelist integration
prowler/providers/linode/lib/service/service.py, prowler/providers/linode/lib/mutelist/mutelist.py, prowler/lib/check/check.py, prowler/config/linode_mutelist_example.yaml
LinodeService base class is created with MAX_WORKERS=10 thread pool and __threading_call__ method for concurrent service-level iteration with per-item exception logging; LinodeMutelist.is_finding_muted method resolves region/resource id and calls base Mutelist.is_muted; execute in check.py gains a linode branch to populate account_id in mute args; example mutelist YAML demonstrates account/region/resource/tag matching.
Account inventory and 2FA check
prowler/providers/linode/services/account/account_service.py, prowler/providers/linode/services/account/account_client.py, prowler/providers/linode/services/account/account_user_2fa_enabled/*
AccountService fetches client.account.users() and maps each into a User model (username, email, tfa_enabled, restricted) with error handling; account_client singleton exports the service; account_user_2fa_enabled check validates each user's tfa_enabled flag and includes metadata JSON with high severity/IAM categorization.
Firewall inventory and six firewall policy checks
prowler/providers/linode/services/firewall/firewall_service.py, prowler/providers/linode/services/firewall/firewall_client.py, prowler/providers/linode/services/firewall/*/*
FirewallService fetches firewalls via client.networking.firewalls(), parses FirewallRule objects from rules with protocol/action/ports/IPv4/IPv6, and populates Firewall model with status/attached_devices_count/inbound_outbound policies and rules; six checks implemented: firewall_status_enabled (high severity), firewall_assigned_to_devices (medium), firewall_default_inbound_policy_drop (high), firewall_default_outbound_policy_drop (high), firewall_inbound_rules_configured (low), firewall_outbound_rules_configured (low), each with metadata JSON and categorization (internet-exposed).
Instance inventory and resilience/encryption checks
prowler/providers/linode/services/instance/instance_service.py, prowler/providers/linode/services/instance/instance_client.py, prowler/providers/linode/services/instance/*/*
InstanceService fetches instances via client.linode.instances() and maps into Instance model with fields id, label, region, status, backups_enabled, disk_encryption, watchdog_enabled, and tags, with error-safe fallback defaults; three checks implemented: instance_backups_enabled (resilience), instance_disk_encryption_enabled (encryption/high severity), instance_watchdog_enabled (resilience/medium), each with metadata JSON.
Comprehensive test coverage: provider, services, checks, output, and metadata
tests/providers/linode/linode_fixtures.py, tests/providers/linode/linode_provider_test.py, tests/providers/linode/linode_metadata_test.py, tests/providers/linode/lib/mutelist/, tests/providers/linode/services/account/, tests/providers/linode/services/firewall/, tests/providers/linode/services/instance/, tests/lib/outputs/finding_test.py, tests/lib/cli/parser_test.py
Test fixtures define provider constants and factory; provider tests cover session/identity/connection scenarios; service tests validate API response parsing and error handling; check tests verify PASS/FAIL logic and resource identifiers for all eight checks; output tests validate account_uid derivation with fallbacks; metadata tests ensure Provider/CheckID consistency across all check definitions; parser tests include Linode in provider list.
User documentation, release notes, CI, and dependencies
README.md, docs/docs.json, docs/user-guide/providers/linode/*, prowler/CHANGELOG.md, .github/workflows/sdk-tests.yml, .github/labeler.yml, pyproject.toml
Linode row (Unofficial, CLI interface) added to README provider table; docs navigation adds Linode group with getting-started and authentication pages covering PAT creation, LINODE_TOKEN environment variable, required OAuth scopes, and CI/CD examples; changelog entry announces support; SDK test workflow adds Linode pytest step with coverage reporting; labeler adds provider/linode rule; linode-api4==5.44.0 added to runtime dependencies.

Sequence Diagram(s)

sequenceDiagram
  participant CLI as prowler CLI
  participant Init as Provider.init_global_provider
  participant LinodeProvider
  participant LinodeAPI as Linode API
  participant Service as Account/Firewall/InstanceService
  participant Check as Check.execute()
  participant Report as Finding/HTML/Report

  CLI->>Init: arguments.provider == "linode"
  Init->>LinodeProvider: __init__(token, config, mutelist)
  LinodeProvider->>LinodeProvider: setup_session(LINODE_TOKEN)
  LinodeProvider->>LinodeAPI: validate token
  LinodeProvider->>LinodeProvider: setup_identity()
  LinodeProvider->>LinodeAPI: profile() / account()
  LinodeAPI-->>LinodeProvider: username/email/account_id
  Init-->>CLI: LinodeProvider registered globally
  CLI->>Service: Service(get_global_provider())
  Service->>LinodeAPI: users() / firewalls() / instances()
  LinodeAPI-->>Service: raw resource data
  Service-->>CLI: populated User/Firewall/Instance models
  CLI->>Check: execute()
  Check->>Service: iterate service.users/firewalls/instances
  Check-->>CLI: list[CheckReportLinode]
  CLI->>Report: Finding.generate_output(check_output, identity)
  Report-->>CLI: rendered output with account_uid/credentials/region
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Suggested reviewers

  • danibarranqueroo
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 31.45% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description check ✅ Passed The PR description is comprehensive and follows the repository template structure with context, description of changes, detailed steps to review, and a completed checklist.
Title check ✅ Passed The title clearly and specifically describes the main change: adding Linode provider support with three services (administration, compute, networking) and related checks.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions

github-actions Bot commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Conflict Markers Resolved

All conflict markers have been successfully resolved in this pull request.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 38

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
prowler/providers/linode/services/account/account_user_2fa_enabled/account_user_2fa_enabled.metadata.json (1)

18-37: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Fill Required Metadata Contract Fields

Remediation.Code.CLI is empty and compliance version metadata is missing. This breaks the required check metadata contract and can degrade downstream compliance/report consumption.

As per coding guidelines, in prowler/** metadata, “Remediation.Code.CLI ... required and non-empty” and “Compliance Version must be non-empty.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@prowler/providers/linode/services/account/account_user_2fa_enabled/account_user_2fa_enabled.metadata.json`
around lines 18 - 37, In the account_user_2fa_enabled.metadata.json file, fill
the empty Remediation.Code.CLI field with appropriate CLI command instructions
for enabling two-factor authentication in Linode, similar to how the Other field
is populated with step-by-step guidance. Additionally, add the required
Compliance Version metadata field (which is currently missing from the metadata
contract) with an appropriate version value to ensure the check metadata
contract is fully satisfied and downstream compliance reporting functions
correctly.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/user-guide/providers/linode/authentication.mdx`:
- Around line 1-6: The Linode authentication documentation is missing the
Version Badge component that indicates when Linode provider support was
introduced. Add a VersionBadge component with the appropriate version number
immediately after the YAML frontmatter closing (--) and before the main content
that begins with "Prowler for Linode uses a Personal Access Token". Place the
VersionBadge on its own line to maintain consistency with documentation
standards.

In `@docs/user-guide/providers/linode/getting-started-linode.mdx`:
- Around line 1-6: The document is missing the Version Badge component that
indicates when Linode provider support was introduced in Prowler. Add the
VersionBadge component immediately after the frontmatter closing (---) and
before the description paragraph that begins with "Prowler for Linode scans...".
The VersionBadge should be placed on its own line and include the appropriate
version attribute indicating when Linode support was introduced.
- Line 18: In the getting-started-linode.mdx file, minimize second-person
pronouns in the sentence that begins with "Once you have your Personal Access
Token, you can run Prowler for Linode...". Restructure this sentence to reduce
explicit use of "you" and "your" by rephrasing it in a more passive or
imperative form, such as changing it to use "Once authenticated with a Personal
Access Token, run Prowler for Linode using either an environment variable or CLI
argument:" to maintain clarity while following documentation style guidelines.
- Line 57: The table entry describing the firewall resource uses inconsistent
capitalization for Linode's official product name. In the table row for the
firewall resource (marked with backtick firewall), change "Cloud firewall" to
"Cloud Firewall" to match Linode's official branding and maintain consistent
capitalization of proper product names throughout the documentation.

In `@prowler/config/linode_mutelist_example.yaml`:
- Line 2: In the comment "### Account == <Linode Account EUUID>", replace the
typo "EUUID" with "UUID" to match standard Linode terminology and ensure the
example configuration file uses correct terminology.

In `@prowler/providers/linode/exceptions/exceptions.py`:
- Around line 27-80: Add type hints and Google-style docstrings to all public
exception constructors in the file. For the LinodeBaseException.__init__ method,
add type hints for parameters code (int), file (optional), original_exception
(optional), and message (optional), plus a return type of None. For each
subclass constructor (LinodeCredentialsError.__init__,
LinodeAuthenticationError.__init__, LinodeSessionError.__init__, and
LinodeIdentityError.__init__), add the same type hints for their parameters and
return type. Additionally, add a method docstring to each __init__ method that
briefly describes what the constructor does, following Google docstring style
format with an Args section if applicable.

In `@prowler/providers/linode/lib/arguments/arguments.py`:
- Line 4: The public method init_parser in the arguments parser class is missing
type hints. Add type annotations to the method signature by specifying the
return type. Since this is a public function (no leading underscore), it
requires type hints per the Python coding guidelines. Add the appropriate return
type annotation after the method parameters, such as -> None if the method
doesn't return a value, or the specific type if it returns an argument parser
instance or other object.

In `@prowler/providers/linode/lib/mutelist/mutelist.py`:
- Around line 9-20: The is_finding_muted method is missing a docstring that
explains its purpose and parameters. Add a docstring to the is_finding_muted
method that describes what it does (determines whether a finding is muted),
documents all parameters (self, finding as CheckReportLinode, and account_id as
str), and explains the return type (bool). The docstring should follow the
project's documentation standards and provide sufficient context for developers
using this method.

In `@prowler/providers/linode/lib/service/service.py`:
- Around line 12-20: The __init__ method in the LinodeProvider service class is
missing a return type hint and a docstring. Add `-> None` as the return type
hint after the method signature closing parenthesis, and add a docstring
immediately after the method definition that describes the initialization of the
service with the provider, client, and other configuration attributes. This
aligns with the coding guidelines requiring type hints for all public functions
and docstrings for all methods.
- Line 19: The ThreadPoolExecutor instance created as self.thread_pool in the
__init__ method needs explicit cleanup to ensure threads are properly shut down.
Add a __del__ method to the service class that calls
self.thread_pool.shutdown(wait=True) to gracefully terminate all worker threads
when the service instance is garbage collected, or alternatively implement
context manager support by adding __enter__ and __exit__ methods that handle the
ThreadPoolExecutor lifecycle properly. This ensures threads are cleaned up
promptly rather than relying on garbage collection.
- Around line 21-41: Add type hints to the __threading_call__ method to comply
with coding guidelines. The call parameter should be typed as a Callable that
accepts an item and returns an optional result, the iterator parameter should be
typed to accept either a list or an iterable of items, and the method's return
type should be specified as returning a list. Ensure the type hints accurately
reflect how the parameters are used within the method (call is invoked with each
item, iterator can be a list or converted to one, and the method returns a list
of results).

In `@prowler/providers/linode/linode_provider.py`:
- Around line 40-48: Add complete type hints and Google-style docstrings to all
public methods in the LinodeProvider class. Specifically, ensure the __init__
method and all other public methods (referenced at lines 76-95 and 187-187) have
return type hints in their signatures and comprehensive docstrings that describe
the purpose, parameters, return values, and any exceptions. Follow Google
documentation style format with proper sections for Args, Returns, and Raises
where applicable.
- Around line 44-45: The LinodeProvider class initialization uses a mutable
default argument `fixer_config: dict = {}` which causes state to be shared
across instances. Change the default value from `{}` to `None` in the parameter
definition at line 44. Then in the method body, add a check to initialize
fixer_config to an empty dictionary if it is None (similar pattern: `if
fixer_config is None: fixer_config = {}`). Apply the same fix to the other
mutable default argument mentioned at line 65.

In `@prowler/providers/linode/models.py`:
- Around line 27-38: The LinodeOutputOptions.__init__ method is missing type
hints for the public parameters arguments and bulk_checks_metadata, and it lacks
a method docstring. Add type annotations to these parameters (you may need to
determine the appropriate types based on the parent class and usage context),
and add a comprehensive Google-style docstring to the __init__ method that
describes the purpose of the method, documents each parameter with its type and
description, and explains any relevant behavior.

In `@prowler/providers/linode/services/account/account_service.py`:
- Around line 23-28: Add type annotations and a Google-style docstring to the
__init__ method in the account service class. The __init__ method should have
the provider parameter properly annotated and a return type annotation of None,
along with a docstring explaining the initialization of the account service.
Additionally, add a return type annotation of None to the _describe_users method
to complete the type hints for both methods.
- Around line 21-25: The `users` list is defined as a class-level attribute in
AccountService, causing all instances to share the same list object which leads
to state accumulation and duplicate findings. Move the `users` list
initialization from the class level to the instance level by setting `self.users
= []` inside the `__init__` method before calling `self._describe_users()`, so
each AccountService instance has its own independent users list that gets
properly reset on re-instantiation.

In
`@prowler/providers/linode/services/account/account_user_2fa_enabled/account_user_2fa_enabled.py`:
- Line 8: The execute() method is missing a Google-style docstring as required
by prowler documentation standards. Add a docstring immediately after the
execute() method definition that follows Google style documentation format,
including a description of what the method does and documentation of the return
type (list[CheckReportLinode]) to comply with the codebase documentation
requirements.

In
`@prowler/providers/linode/services/firewall/firewall_assigned_to_devices/firewall_assigned_to_devices.metadata.json`:
- Line 20: In the firewall_assigned_to_devices metadata file, you need to
populate two required fields according to the metadata contract. First, replace
the empty string value for the Remediation.Code.CLI field with an appropriate
non-empty CLI command that describes how to remediate the firewall configuration
issue. Second, ensure there is a non-empty Compliance Version field in the
metadata (add it if missing) with an appropriate version value. Both fields must
contain non-empty values to satisfy the check metadata requirements.

In
`@prowler/providers/linode/services/firewall/firewall_assigned_to_devices/firewall_assigned_to_devices.py`:
- Line 8: The execute() method is missing a Google-style docstring. Add a
properly formatted Google-style docstring to the execute() method that documents
its purpose, return type, and any relevant details about what the method does.
The docstring should follow the Google documentation format and be placed
immediately after the method signature.
- Around line 11-23: The firewall check relies solely on
fw.attached_devices_count which can report a count even when the upstream
fw.devices list is empty due to rule parsing failures. Modify the condition that
checks fw.attached_devices_count to also verify that fw.devices is not empty and
contains actual device data, ensuring the firewall's device assignment status is
based on successfully populated device information rather than just a count that
might be stale from partial data retrieval.

In
`@prowler/providers/linode/services/firewall/firewall_default_inbound_policy_drop/firewall_default_inbound_policy_drop.metadata.json`:
- Line 20: The metadata file has two required fields that are missing or empty:
the Remediation.Code.CLI field on line 20 is set to an empty string and the
Compliance Version field is either missing or empty. To fix this, populate the
Remediation.Code.CLI field with actual CLI remediation steps that describe how
to fix the firewall default inbound policy drop issue, and add or update the
Compliance Version field to include a non-empty value. Both fields are required
by the check metadata contract and must contain meaningful content to comply
with coding guidelines.

In
`@prowler/providers/linode/services/firewall/firewall_default_inbound_policy_drop/firewall_default_inbound_policy_drop.py`:
- Line 8: The execute() method is missing a Google-style docstring. Add a
docstring immediately after the method signature that describes what the method
does, its return type, and any relevant details about the check it performs.
Follow Google style documentation format with a summary line, detailed
description if needed, and a Returns section documenting the
list[CheckReportLinode] return type.

In
`@prowler/providers/linode/services/firewall/firewall_default_outbound_policy_drop/firewall_default_outbound_policy_drop.metadata.json`:
- Line 20: The metadata file contains empty required fields that violate the
check metadata contract. Locate the empty "CLI" field under Remediation.Code and
populate it with an actual remediation command appropriate for the Linode
Firewall default outbound policy drop check. Additionally, identify the
Compliance Version field in the metadata and ensure it contains a non-empty
value. Both fields must be populated according to the coding guidelines for
metadata validation.

In
`@prowler/providers/linode/services/firewall/firewall_default_outbound_policy_drop/firewall_default_outbound_policy_drop.py`:
- Line 8: The execute() method is missing a Google-style docstring which is
required per coding guidelines. Add a Google-style docstring to the execute()
method that documents its purpose, parameters (if any), return type
(list[CheckReportLinode]), and any relevant details about what the method does.
The docstring should be placed immediately after the method signature and follow
the standard Google docstring format with sections for Summary, Returns, and any
other relevant sections.

In
`@prowler/providers/linode/services/firewall/firewall_inbound_rules_configured/firewall_inbound_rules_configured.metadata.json`:
- Line 20: The firewall_inbound_rules_configured.metadata.json file has two
required metadata fields that are missing or empty: the `Remediation.Code.CLI`
field (at line 20) is set to an empty string and must be populated with an
actual CLI remediation command, and a Compliance Version field must be added and
set to a non-empty value. Update both of these fields in the metadata.json file
to satisfy the check metadata contract requirements.

In
`@prowler/providers/linode/services/firewall/firewall_inbound_rules_configured/firewall_inbound_rules_configured.py`:
- Line 8: The execute() method is missing a Google-style docstring. Add a
docstring immediately after the method signature that includes a brief summary
of what the method does, followed by a Returns section that documents the return
type list[CheckReportLinode] and describes what the list contains. Follow
Google's Python style guide format with proper indentation and formatting.

In
`@prowler/providers/linode/services/firewall/firewall_outbound_rules_configured/firewall_outbound_rules_configured.metadata.json`:
- Line 20: The CLI field in the Remediation.Code section of the
firewall_outbound_rules_configured metadata file is empty, which violates the
coding guideline requiring this field to be non-empty. Fill in the CLI field
with an appropriate CLI command for configuring Linode firewall outbound rules,
or if no such command exists, use the placeholder text "Not available via CLI"
to indicate that remediation cannot be performed through the command line
interface.

In `@prowler/providers/linode/services/firewall/firewall_service.py`:
- Around line 39-44: The __init__ and _describe_firewalls methods in the
firewall_service.py file are missing proper type hints and Google-style
documentation. Add return type hint (-> None) to both the __init__ constructor
and the _describe_firewalls method, and provide a complete Google-style
docstring for __init__ that documents the provider parameter and its purpose.
Enhance the existing _describe_firewalls docstring to follow Google style format
with proper sections for Args, Returns, and any Raises if applicable, ensuring
it clearly describes what the method does and any parameters it accepts.
- Around line 37-41: The `firewalls` attribute is currently defined at class
scope, causing all instances of `FirewallService` to share the same list, which
leads to state leakage and stale/duplicate findings when the service is
recreated. Move the `firewalls: List[Firewall] = []` initialization from the
class level into the `__init__` method so that each instance has its own
independent list, ensuring no state is shared between service instances.

In
`@prowler/providers/linode/services/firewall/firewall_status_enabled/firewall_status_enabled.metadata.json`:
- Around line 18-38: The metadata file has two empty required fields that need
to be populated. First, fill in the Remediation.Code.CLI field with the
appropriate CLI commands for enabling a Linode Cloud Firewall (remove the empty
string value and provide actual CLI instructions). Second, add the missing
Compliance Version metadata to the root level of the JSON object with the
appropriate version information according to Prowler's compliance metadata
guidelines. Ensure both fields are non-empty strings that clearly document the
remediation steps and compliance tracking information.

In
`@prowler/providers/linode/services/firewall/firewall_status_enabled/firewall_status_enabled.py`:
- Line 8: The execute() method in the firewall_status_enabled.py file is missing
a Google-style docstring, which is required by the repository's coding
guidelines. Add a Google-style docstring to the execute() method that describes
its purpose, parameters (if any), and return type. The docstring should follow
Google's documentation format with sections like Args, Returns, and Raises as
appropriate for this method.

In
`@prowler/providers/linode/services/instance/instance_disk_encryption_enabled/instance_disk_encryption_enabled.metadata.json`:
- Line 21: The CLI remediation field under Remediation.Code in the
instance_disk_encryption_enabled.metadata.json file is empty, which violates the
coding guideline requiring non-empty remediation fields. Populate the empty
"CLI" field with either a concrete linode-cli command demonstrating how to
enable disk encryption on a Linode instance (for example, a command with the
--disk_encryption enabled flag), or if disk encryption cannot be enabled on
existing instances post-creation, use a descriptive placeholder string such as
"Not available for existing instances" to clearly communicate this limitation.

In
`@prowler/providers/linode/services/instance/instance_watchdog_enabled/instance_watchdog_enabled.py`:
- Line 8: The execute() method is missing a docstring which violates the coding
guidelines requiring Google-style documentation for all methods. Add a docstring
to the execute() method that describes what the method does, its return type,
and any relevant details about the check being performed. The docstring should
follow Google style format and be placed immediately after the method signature
before the method body.

In
`@tests/providers/linode/services/account/account_user_2fa_enabled/account_user_2fa_enabled_test.py`:
- Around line 11-12: The code assigns `account_client` to the `mock.MagicMock`
class itself instead of creating an instance of it, which causes the subsequent
assignment to the `users` attribute to mutate the global mock class and pollute
test state. Replace `mock.MagicMock` with `mock.MagicMock()` (add parentheses to
instantiate) on all three occurrences: line 11, line 34, and line 67 so that
each test gets its own isolated mock instance rather than mutating the shared
class.

In
`@tests/providers/linode/services/firewall/firewall_assigned_to_devices/firewall_assigned_to_devices_test.py`:
- Around line 9-10: The firewall_client variable is being assigned the MagicMock
class itself instead of an instance of it (missing parentheses). This causes
subsequent assignments to firewall_client.firewalls to mutate a shared class
attribute across all tests. Fix this by changing mock.MagicMock to
mock.MagicMock() (with parentheses) to create independent instances. Apply this
fix at all three locations where firewall_client is instantiated (lines 9, 32,
and 70).

In `@tests/providers/linode/services/firewall/linode_firewall_service_test.py`:
- Around line 103-110: The test modifies the MagicMock class at the global level
using type(fw).rules = property(...), which causes the property modification to
leak into other tests and affect any subsequent mocks that access the rules
attribute. Instead of modifying the class-level property on the fw instance,
configure the instance-level behavior directly using PropertyMock or side_effect
to make the fw.rules attribute raise the exception only for this specific mock
instance without affecting the MagicMock class globally.

In
`@tests/providers/linode/services/instance/instance_watchdog_enabled/instance_watchdog_enabled_test.py`:
- Line 11: In the test file, locate all three instances where instance_client is
assigned to mock.MagicMock without parentheses. Fix each assignment by changing
instance_client = mock.MagicMock to instance_client = mock.MagicMock() to
properly instantiate the MagicMock object instead of referencing the class
itself. This applies to the assignments on lines 11, 34, and 70, ensuring each
test method creates its own isolated mock instance rather than sharing a
class-level attribute.

In `@tests/providers/linode/services/instance/linode_instance_service_test.py`:
- Around line 8-31: Add type hints to the helper functions `_mock_instance` and
`_build_service` to improve code clarity and maintainability. For
`_mock_instance`, add type hints to each parameter (id as int, label as str,
region as str, status as str, backups_enabled as bool, disk_encryption as str,
watchdog_enabled as bool, tags as list or None) and specify the return type as
MagicMock. For `_build_service`, add type hints to the parameters
(linode_instances_return as list or None, linode_instances_side_effect as
Exception or None) and specify the return type as InstanceService.

---

Outside diff comments:
In
`@prowler/providers/linode/services/account/account_user_2fa_enabled/account_user_2fa_enabled.metadata.json`:
- Around line 18-37: In the account_user_2fa_enabled.metadata.json file, fill
the empty Remediation.Code.CLI field with appropriate CLI command instructions
for enabling two-factor authentication in Linode, similar to how the Other field
is populated with step-by-step guidance. Additionally, add the required
Compliance Version metadata field (which is currently missing from the metadata
contract) with an appropriate version value to ensure the check metadata
contract is fully satisfied and downstream compliance reporting functions
correctly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 4fb43188-4752-4bdb-a087-621763d08d3b

📥 Commits

Reviewing files that changed from the base of the PR and between 5ec4a1c and e51c1a8.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock, !**/uv.lock
📒 Files selected for processing (87)
  • README.md
  • docs/docs.json
  • docs/user-guide/providers/linode/authentication.mdx
  • docs/user-guide/providers/linode/getting-started-linode.mdx
  • prowler/__main__.py
  • prowler/compliance/linode/__init__.py
  • prowler/config/config.py
  • prowler/config/linode_mutelist_example.yaml
  • prowler/lib/check/check.py
  • prowler/lib/check/models.py
  • prowler/lib/cli/parser.py
  • prowler/lib/outputs/finding.py
  • prowler/lib/outputs/html/html.py
  • prowler/lib/outputs/outputs.py
  • prowler/lib/outputs/summary_table.py
  • prowler/providers/common/provider.py
  • prowler/providers/linode/__init__.py
  • prowler/providers/linode/exceptions/__init__.py
  • prowler/providers/linode/exceptions/exceptions.py
  • prowler/providers/linode/lib/__init__.py
  • prowler/providers/linode/lib/arguments/__init__.py
  • prowler/providers/linode/lib/arguments/arguments.py
  • prowler/providers/linode/lib/mutelist/__init__.py
  • prowler/providers/linode/lib/mutelist/mutelist.py
  • prowler/providers/linode/lib/service/__init__.py
  • prowler/providers/linode/lib/service/service.py
  • prowler/providers/linode/linode_provider.py
  • prowler/providers/linode/models.py
  • prowler/providers/linode/services/__init__.py
  • prowler/providers/linode/services/account/__init__.py
  • prowler/providers/linode/services/account/account_client.py
  • prowler/providers/linode/services/account/account_service.py
  • prowler/providers/linode/services/account/account_user_2fa_enabled/__init__.py
  • prowler/providers/linode/services/account/account_user_2fa_enabled/account_user_2fa_enabled.metadata.json
  • prowler/providers/linode/services/account/account_user_2fa_enabled/account_user_2fa_enabled.py
  • prowler/providers/linode/services/firewall/__init__.py
  • prowler/providers/linode/services/firewall/firewall_assigned_to_devices/__init__.py
  • prowler/providers/linode/services/firewall/firewall_assigned_to_devices/firewall_assigned_to_devices.metadata.json
  • prowler/providers/linode/services/firewall/firewall_assigned_to_devices/firewall_assigned_to_devices.py
  • prowler/providers/linode/services/firewall/firewall_client.py
  • prowler/providers/linode/services/firewall/firewall_default_inbound_policy_drop/__init__.py
  • prowler/providers/linode/services/firewall/firewall_default_inbound_policy_drop/firewall_default_inbound_policy_drop.metadata.json
  • prowler/providers/linode/services/firewall/firewall_default_inbound_policy_drop/firewall_default_inbound_policy_drop.py
  • prowler/providers/linode/services/firewall/firewall_default_outbound_policy_drop/__init__.py
  • prowler/providers/linode/services/firewall/firewall_default_outbound_policy_drop/firewall_default_outbound_policy_drop.metadata.json
  • prowler/providers/linode/services/firewall/firewall_default_outbound_policy_drop/firewall_default_outbound_policy_drop.py
  • prowler/providers/linode/services/firewall/firewall_inbound_rules_configured/__init__.py
  • prowler/providers/linode/services/firewall/firewall_inbound_rules_configured/firewall_inbound_rules_configured.metadata.json
  • prowler/providers/linode/services/firewall/firewall_inbound_rules_configured/firewall_inbound_rules_configured.py
  • prowler/providers/linode/services/firewall/firewall_outbound_rules_configured/__init__.py
  • prowler/providers/linode/services/firewall/firewall_outbound_rules_configured/firewall_outbound_rules_configured.metadata.json
  • prowler/providers/linode/services/firewall/firewall_outbound_rules_configured/firewall_outbound_rules_configured.py
  • prowler/providers/linode/services/firewall/firewall_service.py
  • prowler/providers/linode/services/firewall/firewall_status_enabled/__init__.py
  • prowler/providers/linode/services/firewall/firewall_status_enabled/firewall_status_enabled.metadata.json
  • prowler/providers/linode/services/firewall/firewall_status_enabled/firewall_status_enabled.py
  • prowler/providers/linode/services/instance/__init__.py
  • prowler/providers/linode/services/instance/instance_backups_enabled/__init__.py
  • prowler/providers/linode/services/instance/instance_backups_enabled/instance_backups_enabled.metadata.json
  • prowler/providers/linode/services/instance/instance_backups_enabled/instance_backups_enabled.py
  • prowler/providers/linode/services/instance/instance_client.py
  • prowler/providers/linode/services/instance/instance_disk_encryption_enabled/__init__.py
  • prowler/providers/linode/services/instance/instance_disk_encryption_enabled/instance_disk_encryption_enabled.metadata.json
  • prowler/providers/linode/services/instance/instance_disk_encryption_enabled/instance_disk_encryption_enabled.py
  • prowler/providers/linode/services/instance/instance_service.py
  • prowler/providers/linode/services/instance/instance_watchdog_enabled/__init__.py
  • prowler/providers/linode/services/instance/instance_watchdog_enabled/instance_watchdog_enabled.metadata.json
  • prowler/providers/linode/services/instance/instance_watchdog_enabled/instance_watchdog_enabled.py
  • pyproject.toml
  • tests/lib/cli/parser_test.py
  • tests/providers/linode/lib/mutelist/fixtures/linode_mutelist.yaml
  • tests/providers/linode/lib/mutelist/linode_mutelist_test.py
  • tests/providers/linode/linode_fixtures.py
  • tests/providers/linode/linode_provider_test.py
  • tests/providers/linode/services/account/account_user_2fa_enabled/account_user_2fa_enabled_test.py
  • tests/providers/linode/services/account/linode_account_service_test.py
  • tests/providers/linode/services/firewall/firewall_assigned_to_devices/firewall_assigned_to_devices_test.py
  • tests/providers/linode/services/firewall/firewall_default_inbound_policy_drop/firewall_default_inbound_policy_drop_test.py
  • tests/providers/linode/services/firewall/firewall_default_outbound_policy_drop/firewall_default_outbound_policy_drop_test.py
  • tests/providers/linode/services/firewall/firewall_inbound_rules_configured/firewall_inbound_rules_configured_test.py
  • tests/providers/linode/services/firewall/firewall_outbound_rules_configured/firewall_outbound_rules_configured_test.py
  • tests/providers/linode/services/firewall/firewall_status_enabled/firewall_status_enabled_test.py
  • tests/providers/linode/services/firewall/linode_firewall_service_test.py
  • tests/providers/linode/services/instance/instance_backups_enabled/instance_backups_enabled_test.py
  • tests/providers/linode/services/instance/instance_disk_encryption_enabled/instance_disk_encryption_enabled_test.py
  • tests/providers/linode/services/instance/instance_watchdog_enabled/instance_watchdog_enabled_test.py
  • tests/providers/linode/services/instance/linode_instance_service_test.py

Comment thread docs/user-guide/providers/linode/authentication.mdx
Comment thread docs/user-guide/providers/linode/getting-started-linode.mdx
Comment thread docs/user-guide/providers/linode/getting-started-linode.mdx Outdated
Comment thread docs/user-guide/providers/linode/getting-started-linode.mdx Outdated
Comment thread prowler/config/linode_mutelist_example.yaml Outdated
Comment thread tests/providers/linode/services/firewall/linode_firewall_service_test.py Outdated
@danibarranqueroo

Copy link
Copy Markdown
Member

Hello @varunmamillapalli! Thanks for this!

We'll try to review this as soon as possible, in the meantime could you share some screenshots of the provider working?

@varunmamillapalli

Copy link
Copy Markdown
Author

Hello @varunmamillapalli! Thanks for this!

We'll try to review this as soon as possible, in the meantime could you share some screenshots of the provider working?

Hi @danibarranqueroo, I have added screenshots to the PR description. Please take a look!

…ion in tests, avoiding shared mutable services

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

♻️ Duplicate comments (4)
prowler/providers/linode/lib/service/service.py (2)

12-12: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add return type hint to __init__ method.

As per coding guidelines, type hints are required for all public functions. The __init__ method is missing the -> None return type hint.

📝 Proposed fix
-    def __init__(self, service: str, provider: LinodeProvider):
+    def __init__(self, service: str, provider: LinodeProvider) -> None:
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@prowler/providers/linode/lib/service/service.py` at line 12, The `__init__`
method in the service class is missing the required return type hint for public
functions. Add the `-> None` return type hint to the `__init__` method signature
after the closing parenthesis of the parameters and before the colon to indicate
that this method returns None, making it compliant with the coding guidelines
that require type hints for all public functions.

Source: Coding guidelines


28-48: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add type hints and expand docstring for __threading_call__ method.

As per coding guidelines, type hints are required for all public functions and docstrings are required for all methods. The __threading_call__ method is missing:

  1. Type hints for call and iterator parameters
  2. Return type hint
  3. Args and Returns sections in the docstring
📝 Proposed fix
+from typing import Any, Callable, Iterable, List
+
-    def __threading_call__(self, call, iterator):
-        """Execute a function across multiple items using threading."""
+    def __threading_call__(
+        self, call: Callable[[Any], Any], iterator: Iterable[Any]
+    ) -> List[Any]:
+        """Execute a function across multiple items using threading.
+
+        Args:
+            call: Callable function to execute on each item.
+            iterator: Iterable of items to process.
+
+        Returns:
+            List of non-None results from the callable.
+        """
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@prowler/providers/linode/lib/service/service.py` around lines 28 - 48, The
__threading_call__ method is missing type hints and complete documentation. Add
type hints to the call parameter (which should be a Callable that accepts an
item and returns an optional result), the iterator parameter (which should
accept an Iterable or List), and the return type (which should be List). Then
expand the existing docstring to include an Args section documenting both
parameters (call should describe it as a callable function to execute on each
item, and iterator should describe it as an iterable or list of items to
process) and a Returns section describing that the method returns a list of
non-None results from the executed function calls.

Source: Coding guidelines

prowler/providers/linode/services/firewall/firewall_service.py (1)

37-42: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Add required type hints and Google-style docstring to service methods.

The __init__ method is missing parameter type hints, a return annotation, and a docstring. The _describe_firewalls method is missing its return type annotation.

As per coding guidelines, prowler/**/*.py requires type hints for all public functions and docstrings for all classes and methods following Google style documentation.

♻️ Proposed fix
-    def __init__(self, provider):
+    def __init__(self, provider) -> None:
+        """Initialize the FirewallService.
+
+        Args:
+            provider: The Linode provider instance.
+        """
         super().__init__("firewall", provider)
         self.firewalls: List[Firewall] = []
         self._describe_firewalls()

-    def _describe_firewalls(self):
+    def _describe_firewalls(self) -> None:
         """Fetch all Linode Cloud Firewalls with their rules."""
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@prowler/providers/linode/services/firewall/firewall_service.py` around lines
37 - 42, The `__init__` method and `_describe_firewalls` method in the Firewall
service class are missing type hints and docstrings required by the coding
guidelines. Add a type hint for the `provider` parameter in the `__init__`
method, add a return annotation of `-> None` to both the `__init__` and
`_describe_firewalls` methods, and add Google-style docstrings to both methods
describing their purpose and parameters. Ensure the docstrings follow the Google
style format with sections for description, args, and returns as appropriate.

Source: Coding guidelines

prowler/providers/linode/services/account/account_service.py (1)

21-26: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Add required type hints and Google-style docstring to service methods.

The __init__ method is missing parameter type hints, a return annotation, and a docstring. The _describe_users method is missing its return type annotation.

As per coding guidelines, prowler/**/*.py requires type hints for all public functions and docstrings for all classes and methods following Google style documentation.

♻️ Proposed fix
-    def __init__(self, provider):
+    def __init__(self, provider) -> None:
+        """Initialize the AccountService.
+
+        Args:
+            provider: The Linode provider instance.
+        """
         super().__init__("account", provider)
         self.users: List[User] = []
         self._describe_users()

-    def _describe_users(self):
+    def _describe_users(self) -> None:
         """Fetch all Linode account users."""
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@prowler/providers/linode/services/account/account_service.py` around lines 21
- 26, The `__init__` method in the account service class is missing parameter
type hints, a return type annotation, and a docstring. Add a type hint for the
`provider` parameter, add a return type annotation of `-> None` to the method
signature, and include a Google-style docstring that describes the
initialization of the account service and what the method does. Additionally,
add the missing return type annotation `-> None` to the `_describe_users` method
to ensure all methods have complete type hints as required by the coding
guidelines.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@prowler/CHANGELOG.md`:
- Line 21: The changelog entry for Linode has two issues: first, the verb "Add"
is redundant since the entry is already under the "### 🚀 Added" section header
which indicates the action; second, "Provider" should be lowercase "provider" to
match changelog conventions. Change the entry from "Add support for Linode cloud
Provider" to "Support for Linode cloud provider" to be consistent with other
entries like "Support for Python 3.13" on line 9 and the lowercase "provider"
pattern used in entries like "AWS provider" on line 10.

In `@prowler/providers/linode/linode_provider.py`:
- Around line 65-66: The __init__ method in the LinodeProvider class has an
incorrect "Returns" section in its docstring that claims it returns a
LinodeProvider instance. Remove the entire "Returns" section (including the
"Returns:" label and the "LinodeProvider: The LinodeProvider instance." line)
from the __init__ docstring, as __init__ methods implicitly return None and
should not have a Returns section according to Python conventions.

In `@prowler/providers/linode/services/instance/instance_service.py`:
- Around line 25-30: Add type hints and Google-style docstrings to the
`__init__` and `_describe_instances` methods in the Instance service class. For
the `__init__` method, add a type hint for the `provider` parameter, add a
return annotation of `-> None`, and add a Google-style docstring that describes
the initialization of the service and its parameters. For the
`_describe_instances` method, add a return annotation of `-> None` to indicate
it does not return a value.

---

Duplicate comments:
In `@prowler/providers/linode/lib/service/service.py`:
- Line 12: The `__init__` method in the service class is missing the required
return type hint for public functions. Add the `-> None` return type hint to the
`__init__` method signature after the closing parenthesis of the parameters and
before the colon to indicate that this method returns None, making it compliant
with the coding guidelines that require type hints for all public functions.
- Around line 28-48: The __threading_call__ method is missing type hints and
complete documentation. Add type hints to the call parameter (which should be a
Callable that accepts an item and returns an optional result), the iterator
parameter (which should accept an Iterable or List), and the return type (which
should be List). Then expand the existing docstring to include an Args section
documenting both parameters (call should describe it as a callable function to
execute on each item, and iterator should describe it as an iterable or list of
items to process) and a Returns section describing that the method returns a
list of non-None results from the executed function calls.

In `@prowler/providers/linode/services/account/account_service.py`:
- Around line 21-26: The `__init__` method in the account service class is
missing parameter type hints, a return type annotation, and a docstring. Add a
type hint for the `provider` parameter, add a return type annotation of `->
None` to the method signature, and include a Google-style docstring that
describes the initialization of the account service and what the method does.
Additionally, add the missing return type annotation `-> None` to the
`_describe_users` method to ensure all methods have complete type hints as
required by the coding guidelines.

In `@prowler/providers/linode/services/firewall/firewall_service.py`:
- Around line 37-42: The `__init__` method and `_describe_firewalls` method in
the Firewall service class are missing type hints and docstrings required by the
coding guidelines. Add a type hint for the `provider` parameter in the
`__init__` method, add a return annotation of `-> None` to both the `__init__`
and `_describe_firewalls` methods, and add Google-style docstrings to both
methods describing their purpose and parameters. Ensure the docstrings follow
the Google style format with sections for description, args, and returns as
appropriate.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 7b8cf6fc-e435-41e2-b7d9-3507c3a67a76

📥 Commits

Reviewing files that changed from the base of the PR and between e51c1a8 and d88eb20.

📒 Files selected for processing (32)
  • README.md
  • docs/user-guide/providers/linode/authentication.mdx
  • docs/user-guide/providers/linode/getting-started-linode.mdx
  • prowler/CHANGELOG.md
  • prowler/config/linode_mutelist_example.yaml
  • prowler/providers/linode/lib/mutelist/mutelist.py
  • prowler/providers/linode/lib/service/service.py
  • prowler/providers/linode/linode_provider.py
  • prowler/providers/linode/services/account/account_service.py
  • prowler/providers/linode/services/account/account_user_2fa_enabled/account_user_2fa_enabled.py
  • prowler/providers/linode/services/firewall/firewall_assigned_to_devices/firewall_assigned_to_devices.py
  • prowler/providers/linode/services/firewall/firewall_default_inbound_policy_drop/firewall_default_inbound_policy_drop.py
  • prowler/providers/linode/services/firewall/firewall_default_outbound_policy_drop/firewall_default_outbound_policy_drop.py
  • prowler/providers/linode/services/firewall/firewall_inbound_rules_configured/firewall_inbound_rules_configured.py
  • prowler/providers/linode/services/firewall/firewall_outbound_rules_configured/firewall_outbound_rules_configured.py
  • prowler/providers/linode/services/firewall/firewall_service.py
  • prowler/providers/linode/services/firewall/firewall_status_enabled/firewall_status_enabled.py
  • prowler/providers/linode/services/instance/instance_backups_enabled/instance_backups_enabled.py
  • prowler/providers/linode/services/instance/instance_disk_encryption_enabled/instance_disk_encryption_enabled.py
  • prowler/providers/linode/services/instance/instance_service.py
  • prowler/providers/linode/services/instance/instance_watchdog_enabled/instance_watchdog_enabled.py
  • tests/providers/linode/services/account/account_user_2fa_enabled/account_user_2fa_enabled_test.py
  • tests/providers/linode/services/firewall/firewall_assigned_to_devices/firewall_assigned_to_devices_test.py
  • tests/providers/linode/services/firewall/firewall_default_inbound_policy_drop/firewall_default_inbound_policy_drop_test.py
  • tests/providers/linode/services/firewall/firewall_default_outbound_policy_drop/firewall_default_outbound_policy_drop_test.py
  • tests/providers/linode/services/firewall/firewall_inbound_rules_configured/firewall_inbound_rules_configured_test.py
  • tests/providers/linode/services/firewall/firewall_outbound_rules_configured/firewall_outbound_rules_configured_test.py
  • tests/providers/linode/services/firewall/firewall_status_enabled/firewall_status_enabled_test.py
  • tests/providers/linode/services/firewall/linode_firewall_service_test.py
  • tests/providers/linode/services/instance/instance_backups_enabled/instance_backups_enabled_test.py
  • tests/providers/linode/services/instance/instance_disk_encryption_enabled/instance_disk_encryption_enabled_test.py
  • tests/providers/linode/services/instance/instance_watchdog_enabled/instance_watchdog_enabled_test.py

Comment thread prowler/CHANGELOG.md Outdated
Comment thread prowler/providers/linode/linode_provider.py Outdated
Comment thread prowler/providers/linode/services/compute/compute_service.py
@danibarranqueroo danibarranqueroo requested a review from a team as a code owner June 19, 2026 09:54
@github-actions github-actions Bot added the github_actions Pull requests that update GitHub Actions code label Jun 19, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

♻️ Duplicate comments (1)
prowler/providers/linode/services/firewall/firewall_outbound_rules_configured/firewall_outbound_rules_configured.metadata.json (1)

10-10: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Populate the outbound-rules CLI remediation.

Linode's docs already expose linode-cli firewalls rules-update, so leaving Remediation.Code.CLI blank here removes a supported remediation path. (techdocs.akamai.com)

Also applies to: 20-28

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@prowler/providers/linode/services/firewall/firewall_outbound_rules_configured/firewall_outbound_rules_configured.metadata.json`
at line 10, The Remediation.Code.CLI field in the
firewall_outbound_rules_configured metadata is empty, which prevents users from
having a documented CLI remediation path. Populate the Remediation.Code.CLI
field with the appropriate linode-cli command for updating firewall outbound
rules using the linode-cli firewalls rules-update command that is already
documented in Linode's API reference. Ensure this is consistent across all
locations mentioned (lines 10-28) where similar remediation fields need to be
filled in for this check.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/user-guide/providers/linode/authentication.mdx`:
- Line 9: The documentation at the beginning of the authentication section makes
an overly absolute security claim by stating the token is "never exposed in
shell history or process listings." Reword this sentence to make a narrower
guarantee that using an environment variable keeps the token off the command
line itself, without claiming it prevents exposure through other means. Keep the
accurate parts about Prowler reading exclusively from the LINODE_TOKEN
environment variable and having no credential CLI flags, but remove the absolute
language about preventing all exposure methods.

In `@docs/user-guide/providers/linode/getting-started-linode.mdx`:
- Line 26: The documentation in the Linode getting-started guide overstates the
security benefit of using the LINODE_TOKEN environment variable. Revise the
sentence starting at line 26 to accurately reflect that setting the token as an
environment variable prevents it from being exposed in shell history and command
line process listings (since it's not passed as a CLI argument), rather than
claiming it is never exposed in any context. The statement should be more
precise about the actual security protection provided by the environment
variable approach, acknowledging that this method avoids command line exposure
specifically.

In `@tests/providers/linode/linode_metadata_test.py`:
- Around line 8-11: The parametrize decorator uses a glob pattern that could
return an empty list, causing the test to pass vacuously without validating
anything. Extract the glob result from
Path("prowler/providers/linode").glob("services/**/*.metadata.json") into a
shared variable before the parametrize decorator, then add an assert statement
to verify the list is not empty before using it in the parametrize call. This
ensures the test will fail in CI if the metadata file discovery breaks.

---

Duplicate comments:
In
`@prowler/providers/linode/services/firewall/firewall_outbound_rules_configured/firewall_outbound_rules_configured.metadata.json`:
- Line 10: The Remediation.Code.CLI field in the
firewall_outbound_rules_configured metadata is empty, which prevents users from
having a documented CLI remediation path. Populate the Remediation.Code.CLI
field with the appropriate linode-cli command for updating firewall outbound
rules using the linode-cli firewalls rules-update command that is already
documented in Linode's API reference. Ensure this is consistent across all
locations mentioned (lines 10-28) where similar remediation fields need to be
filled in for this check.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 1f0558ac-bb57-4656-9ab7-9fd24373d358

📥 Commits

Reviewing files that changed from the base of the PR and between 0fd957d and d717856.

📒 Files selected for processing (26)
  • .github/labeler.yml
  • .github/workflows/sdk-tests.yml
  • README.md
  • docs/docs.json
  • docs/user-guide/providers/linode/authentication.mdx
  • docs/user-guide/providers/linode/getting-started-linode.mdx
  • prowler/CHANGELOG.md
  • prowler/lib/outputs/finding.py
  • prowler/providers/common/provider.py
  • prowler/providers/linode/exceptions/exceptions.py
  • prowler/providers/linode/lib/arguments/arguments.py
  • prowler/providers/linode/lib/mutelist/mutelist.py
  • prowler/providers/linode/linode_provider.py
  • prowler/providers/linode/services/account/account_user_2fa_enabled/account_user_2fa_enabled.metadata.json
  • prowler/providers/linode/services/firewall/firewall_assigned_to_devices/firewall_assigned_to_devices.metadata.json
  • prowler/providers/linode/services/firewall/firewall_default_inbound_policy_drop/firewall_default_inbound_policy_drop.metadata.json
  • prowler/providers/linode/services/firewall/firewall_default_outbound_policy_drop/firewall_default_outbound_policy_drop.metadata.json
  • prowler/providers/linode/services/firewall/firewall_inbound_rules_configured/firewall_inbound_rules_configured.metadata.json
  • prowler/providers/linode/services/firewall/firewall_outbound_rules_configured/firewall_outbound_rules_configured.metadata.json
  • prowler/providers/linode/services/firewall/firewall_service.py
  • prowler/providers/linode/services/firewall/firewall_status_enabled/firewall_status_enabled.metadata.json
  • prowler/providers/linode/services/instance/instance_backups_enabled/instance_backups_enabled.metadata.json
  • prowler/providers/linode/services/instance/instance_disk_encryption_enabled/instance_disk_encryption_enabled.metadata.json
  • prowler/providers/linode/services/instance/instance_watchdog_enabled/instance_watchdog_enabled.metadata.json
  • tests/lib/outputs/finding_test.py
  • tests/providers/linode/linode_metadata_test.py

Comment thread docs/user-guide/providers/linode/authentication.mdx
Comment thread docs/user-guide/providers/linode/getting-started-linode.mdx
Comment thread tests/providers/linode/linode_metadata_test.py
Comment thread prowler/providers/linode/lib/mutelist/mutelist.py Dismissed
Comment thread prowler/providers/linode/services/compute/compute_service.py Fixed
Comment thread prowler/providers/linode/services/compute/compute_service.py Fixed
Comment thread prowler/providers/linode/services/compute/compute_service.py Fixed
@jfagoagas jfagoagas changed the title feat: [New Provider] Add support for Linode provider with account, firewall, and instance services with few initial checks feat: Linode provider with account, firewall, and instance services Jun 19, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@prowler/providers/linode/services/firewall/firewall_assigned_to_devices/firewall_assigned_to_devices.py`:
- Around line 21-29: The issue is that when fw.attached_devices_count is None,
the code uses continue to skip the firewall entirely, which means no finding is
returned for that resource. This violates the requirement that execute() must
return one PASS/FAIL finding per iterated resource. Instead of skipping with
continue, create a FAIL finding for this firewall with a clear status_extended
message that explains the device assignment could not be determined. Use
fw.label and fw.id to identify the resource in the status message, and ensure
the finding is added to the results list so one finding is emitted per firewall
resource.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 6b4ae5d5-c3d1-43ff-81df-64860509a13b

📥 Commits

Reviewing files that changed from the base of the PR and between d717856 and 0c5dd72.

📒 Files selected for processing (6)
  • prowler/providers/linode/services/account/account_service.py
  • prowler/providers/linode/services/firewall/firewall_assigned_to_devices/firewall_assigned_to_devices.py
  • prowler/providers/linode/services/firewall/firewall_service.py
  • tests/providers/linode/services/account/linode_account_service_test.py
  • tests/providers/linode/services/firewall/firewall_assigned_to_devices/firewall_assigned_to_devices_test.py
  • tests/providers/linode/services/firewall/linode_firewall_service_test.py

@HugoPBrito HugoPBrito changed the title feat: Linode provider with account, firewall, and instance services feat(linode): add provider with product-area services Jun 19, 2026
@HugoPBrito HugoPBrito changed the title feat(linode): add provider with product-area services feat(linode): add provider with administration compute and networking services Jun 19, 2026
@codecov

codecov Bot commented Jun 19, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 80.94340% with 101 lines in your changes missing coverage. Please review.
✅ Project coverage is 86.81%. Comparing base (99285d4) to head (f1a7ff4).
⚠️ Report is 11 commits behind head on master.

❗ There is a different number of reports uploaded between BASE (99285d4) and HEAD (f1a7ff4). Click for more details.

HEAD has 1 upload less than BASE
Flag BASE (99285d4) HEAD (f1a7ff4)
api 1 0
Additional details and impacted files
@@            Coverage Diff             @@
##           master   #11633      +/-   ##
==========================================
- Coverage   94.10%   86.81%   -7.30%     
==========================================
  Files         247     1930    +1683     
  Lines       36421    65165   +28744     
==========================================
+ Hits        34274    56572   +22298     
- Misses       2147     8593    +6446     
Flag Coverage Δ
api ?
prowler-py3.10-aws 90.12% <ø> (?)
prowler-py3.10-azure 89.67% <ø> (?)
prowler-py3.10-config 86.81% <80.94%> (?)
prowler-py3.10-external 79.07% <79.81%> (?)
prowler-py3.10-gcp 90.09% <ø> (?)
prowler-py3.10-github 89.40% <ø> (?)
prowler-py3.10-googleworkspace 88.31% <ø> (?)
prowler-py3.10-iac 89.36% <ø> (?)
prowler-py3.10-kubernetes 89.76% <ø> (?)
prowler-py3.10-lib 86.77% <80.94%> (?)
prowler-py3.10-linode 87.92% <83.29%> (?)
prowler-py3.10-m365 89.58% <ø> (?)
prowler-py3.10-mongodbatlas 89.27% <ø> (?)
prowler-py3.10-nhn 89.71% <ø> (?)
prowler-py3.10-okta 89.76% <ø> (?)
prowler-py3.10-openstack 87.92% <ø> (?)
prowler-py3.10-oraclecloud 87.71% <ø> (?)
prowler-py3.10-scaleway 88.07% <ø> (?)
prowler-py3.10-stackit 87.96% <ø> (?)
prowler-py3.10-vercel 88.14% <ø> (?)
prowler-py3.11-aws 90.11% <ø> (?)
prowler-py3.11-azure 89.66% <ø> (?)
prowler-py3.11-config 86.75% <80.94%> (?)
prowler-py3.11-external 79.02% <79.81%> (?)
prowler-py3.11-gcp 90.08% <ø> (?)
prowler-py3.11-github 89.39% <ø> (?)
prowler-py3.11-googleworkspace 88.24% <ø> (?)
prowler-py3.11-iac 89.29% <ø> (?)
prowler-py3.11-kubernetes 89.75% <ø> (?)
prowler-py3.11-lib 86.71% <80.94%> (?)
prowler-py3.11-linode 87.86% <83.29%> (?)
prowler-py3.11-m365 89.51% <ø> (?)
prowler-py3.11-mongodbatlas 89.20% <ø> (?)
prowler-py3.11-nhn 89.70% <ø> (?)
prowler-py3.11-okta 89.75% <ø> (?)
prowler-py3.11-openstack 87.85% <ø> (?)
prowler-py3.11-oraclecloud 87.64% <ø> (?)
prowler-py3.11-scaleway 88.01% <ø> (?)
prowler-py3.11-stackit 87.90% <ø> (?)
prowler-py3.11-vercel 88.07% <ø> (?)
prowler-py3.12-aws 90.11% <ø> (?)
prowler-py3.12-azure 89.67% <ø> (?)
prowler-py3.12-config 86.79% <80.94%> (?)
prowler-py3.12-external 79.05% <79.81%> (?)
prowler-py3.12-gcp 90.09% <ø> (?)
prowler-py3.12-github 89.40% <ø> (?)
prowler-py3.12-googleworkspace 88.29% <ø> (?)
prowler-py3.12-iac 89.34% <ø> (?)
prowler-py3.12-kubernetes 89.75% <ø> (?)
prowler-py3.12-lib 86.75% <80.94%> (?)
prowler-py3.12-linode 87.91% <83.29%> (?)
prowler-py3.12-m365 89.57% <ø> (?)
prowler-py3.12-mongodbatlas 89.25% <ø> (?)
prowler-py3.12-nhn 89.70% <ø> (?)
prowler-py3.12-okta 89.75% <ø> (?)
prowler-py3.12-openstack 87.90% <ø> (?)
prowler-py3.12-oraclecloud 87.69% <ø> (?)
prowler-py3.12-scaleway 88.05% <ø> (?)
prowler-py3.12-stackit 87.95% <ø> (?)
prowler-py3.12-vercel 88.12% <ø> (?)
prowler-py3.13-aws 90.11% <ø> (?)
prowler-py3.13-azure 89.67% <ø> (?)
prowler-py3.13-config 86.80% <80.94%> (?)
prowler-py3.13-external 79.06% <79.81%> (?)
prowler-py3.13-gcp 90.09% <ø> (?)
prowler-py3.13-github 89.40% <ø> (?)
prowler-py3.13-googleworkspace 88.29% <ø> (?)
prowler-py3.13-iac 89.35% <ø> (?)
prowler-py3.13-kubernetes 89.75% <ø> (?)
prowler-py3.13-lib 86.76% <80.94%> (?)
prowler-py3.13-linode 87.91% <83.29%> (?)
prowler-py3.13-m365 89.57% <ø> (?)
prowler-py3.13-mongodbatlas 89.25% <ø> (?)
prowler-py3.13-nhn 89.71% <ø> (?)
prowler-py3.13-okta 89.76% <ø> (?)
prowler-py3.13-openstack 87.90% <ø> (?)
prowler-py3.13-oraclecloud 87.69% <ø> (?)
prowler-py3.13-scaleway 88.06% <ø> (?)
prowler-py3.13-stackit 87.95% <ø> (?)
prowler-py3.13-vercel 88.12% <ø> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

Components Coverage Δ
prowler 86.81% <82.05%> (∅)
api ∅ <ø> (∅)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

community Opened by the Community compliance Issues/PRs related with the Compliance Frameworks documentation github_actions Pull requests that update GitHub Actions code metadata-review output/html Issues/PRs related with the HTML output format

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants