Enhancing Security by Removing Restrictions in Apache NiFi 2
Introduction
Apache NiFi 2.10.0 marks an important milestone in the security evolution of the project,
as the framework no longer reads or enforces the
Restricted
annotation on Processors, Controller Services, or other extensions components. Almost
a decade after initial implementation for version 1.1.0, Apache NiFi API 2.8.0 deprecated the Restricted annotation
for removal, signaling the new direction. On the surface, removing API and implementation support for tagging and
limiting access to more powerful features might appear to be a step backward. As described in
Apache NiFi Improvement Proposal 24, however, realigning framework
security features with enforceable security boundaries provides tangible security benefits. The
Restricted
annotation and associated
RequiredPermission
properties serve as a useful example for considering the possibilities and limitations of the extensible framework that
Apache NiFi provides.
Original Goals
Command and control with rapid reconfiguration is a fundamental feature of Apache NiFi. With this great power, however, comes great potential for unconstrained behavior. Following the initial stable release of Apache NiFi 1, wider adoption surfaced the potential danger of Processors that support extensible operations, such as executing operating system commands, running configurable scripts, and manipulating filesystems. These components provided a bridge between standard features and specialized behaviors, but also opened the door to misuse or misconfiguration. Based on these observations, NIFI-3050 introduced the concept of restricted components with elevated privileges, with new framework policies and authorization checks for limiting access.
Released in 2016 as part of Apache NiFi 1.1.0, the
Restricted
annotation provided component developers the option to indicate selected classes as requiring elevated privileges. The
initial implementation supported a description field without additional modifiers. Building on this annotation,
NIFI-4885 expanded the concept to include more granular
RequiredPermission
modifiers that provided both programmatic and readable values defining the type of access needed. Released in Apache
NiFi 1.6.0, RequiredPermission values included EXECUTE_CODE and WRITE_FILESYSTEM privileges. The Restricted
annotation supported assigning one or more required permissions to a component class based on the behavior implemented.
The concept of elevated privileges, together with descriptive permission enumeration, followed common security patterns found in applications and services that support fine-grained access control. With the ability to annotate specific components and the option to assign selected permissions to users or groups, Apache NiFi presented new configurable security boundaries. These boundaries appeared minimize access to more dangerous features while enabling multiple users to collaborate within a shared system.
Additional Permissions
After the introduction of enumerated required permissions, subsequent Apache NiFi releases expanded the scope of configurable privileges. These new permissions highlighted additional types of elevated access, requiring specific authorization on annotated Processors.
Apache NiFi 1.13.0 added the READ_DISTRIBUTED_FILESYSTEM and WRITE_DISTRIBUTED_FILESYSTEM permissions for
NIFI-7884. The additional permissions applied to Processors
interacting with the Hadoop Distributed File System, differentiating this behavior from
regular filesystem access. With Hadoop libraries providing abstracted support for access to either remote or local
files, the distributed filesystem permission was intended to cover both use cases.
NIFI-8973 introduced new Controller Service abstractions for Kerberos
authentication, and also added ACCESS_TICKET_CACHE to the set of required permissions. Released in Apache NiFi 1.15.0,
the new privilege followed the pattern of the ACCESS_KEYTAB permission, but provided a broader scope to cover
different types of Kerberos authentication caching strategies.
With expanded support for major cloud service providers, Apache NiFi 1.16.0 added ACCESS_ENVIRONMENT_CREDENTIALS
to guard new authentication strategies in several components. As described in
NIFI-9679, credential providers for Amazon Web Services and Google
Cloud Platform include fallback support for reading keys or identities from local environment services. These
credentials granted a level of access to the system, but could include elevated privileges not otherwise accessible to
an application user.
The last addition to the RequiredPermission enumeration came in response to a security finding published as
CVE-2023-36542, resolved in Apache NiFi 1.23.0 and
2.0.0-M1. The resolution for NIFI-11744 introduced the
REFERENCE_REMOTE_RESOURCES permission to indicate the potential for selected components to load resources, such as
driver libraries, from remote web services. The framework provides the general capability to retrieve files from an HTTP
URL, but does not enforce limitations based on the type of file retrieved. As a result, Processors and Controller
Services that support loading drivers from an HTTP URL have the potential to load problematic libraries. This required
permission applied to components such as database connection pooling services and content validation Processors.
The additional required permissions followed existing patterns and aligned with the original goals of the Restricted
annotation, but the need for these new permissions also began to show the limitations of the general approach.
Security Vulnerabilities
Over the course of multiple releases, implementation of the Restricted annotation has been the source of multiple
published security vulnerabilities. These issues included both lack of the annotation itself, and missing authorization
for annotated components.
CVE-2023-36542 highlighted the potential dangers of loading libraries from remote locations, indicating the need for new required permissions. In this case, the general framework feature of remote URL loading, combined with the type of data being loaded, resulted in the need to add a differentiated permission.
CVE-2026-25903 surfaced a gap in authorization
behavior where the framework was missing authorization checks on requests to update configuration properties for
Restricted components. Although this vulnerability required an authorized user to add a Restricted component, and
required the system to be configured for fine-grained authorization, it underscored the challenges inherent in enforcing
privileges at the component level.
CVE-2026-39816 was a relatively straightforward
oversight for a specific Controller Service that allowed users with general modification privileges to execute scripted
Groovy instructions. Although the TinkerpopClientService was not included with the
standard binary distribution of Apache NiFi, the presence of Groovy script execution and the lack of the Restricted
annotation illustrated the importance of strict alignment between component implementation and required annotations.
CVE-2026-44914 disclosed another case of missing
authorization at the framework level, related to a specific REST API method responsible for updating the configuration
of a selected Process Group. With the lack of evaluation for Restricted components, this vulnerability allowed a user
with write permissions to add restricted components without checking for elevated privileges.
For a feature implemented and extended over several years, the number of vulnerabilities may not seem concerning. As a
percentage of all project vulnerabilities, however, the number is more notable. Looking beyond the numbers, the nature
of these vulnerabilities pointed to a more fundamental problem with the concept of Restricted components.
Understanding this problem requires consideration of the
Apache NiFi Security Model and its implications for
both framework features and extension components.
Security Boundary Limitations
As described in the project security model, configuring processing pipelines and specific components for dangerous operations is contrary to best practices, but does not rise to the level of a security vulnerability. In other words, the Apache NiFi framework provides a platform for extensible code execution, but it is the responsibility of the user to follow safe configuration strategies. This distinction does not absolve the project of the obligation to provide secure capabilities, but it emphasizes the inherent dangers of user-provided code and configuration. With that understanding, Apache NiFi has limitations on the security boundaries that the framework provides.
Evaluating Expectations
When designing and building security features, it is essential to align declared capabilities with implemented realities. Product functionality may be more secure than stated, but failure to meet security thresholds is not just a bug, it is a vulnerability. This is one of the primary reasons that a project should define an explicit security model. Certain features such as authentication and TLS communication carry implicit security expectations, but even these features can include configurable options that alter the level of protection provided. Although some basic expectations apply regardless of the application, considering the context of each application is required to determine whether a specific behavior is a feature, a bug, or a vulnerability requiring remediation and publication.
In the context of user configuration, Apache NiFi is both an application and a platform for extension. For this reason, running custom code is a feature of the ExecuteScript Processor, but would be considered a security vulnerability for a REST API method designed to view system status. In contrast, evaluating the behavior of a custom JSON transformation using a REST API method is a feature of some components, but finding that a Processor such as LogMessage allows remote code execution would present a serious concern. Thus both implicit and explicit features must be considered when determining whether a security vulnerability should be published.
Reconsidering Restricted Privileges
In process of reviewing past vulnerabilities and considering structural changes, it became clear that the Restricted
annotation presented an unbridgeable gap between advertised features and supportable capabilities. Although the
framework could limit the creation and modification of a Processor that required execute code privileges, it cannot
prevent code execution from performing other dangerous operations.
An administrator could limit privilege assignment for a specific user to allow creating Processors that referenced remote resources, but the framework cannot prevent the user from loading untrusted libraries that execute operating system commands. Once one type of privileged operation is allowed, it is often possible to do more than the permission implies. The elastic nature of required permissions underscored the mismatch between advertised features and implemented boundaries.
One possible solution would be to implement more thorough enforcement mechanisms. The historical
Java Security Manager
intended to provide policies for controlling Java Virtual Machine operations, but
JEP 411 highlighted the limitations and deprecated the Security Manager for removal.
Strategies such as aspect-oriented method interception might appear as alternative solutions, but the depth and breath
required for implementation present a brittle protection at best. Taking these factors together,
NIP-24 presented deprecation of the Restricted annotation as the
optimal way forward.
Aligning Expectation with Implementation
At first glance, removing security boundaries might appear to be a reduction in the overall security posture of an application. One might ask whether a loose boundary is better than no boundary. The context of such considerations determines the correct answer, but in cases where a security expectation is not satisfied, a partial boundary is more dangerous.
Considering the question from a different perspective, if an administrator grants one privilege and not another, the administrator is trusting that the system will not allow certain ungranted operations. When considering a more general privilege, however, an administrator has the opportunity to consider the full impact of the decision. As described, partial boundaries are not only difficult to maintain, they are also misleading. Accurate alignment of expectation and implementation is essential for building, deploying, and maintaining a secure system.
Deprecation and Incremental Removal
Following the principles of Semantic Versioning,
NIFI-15770 introduced deprecation of the Restricted annotation
for Apache NiFi API 2.8.0. Initial deprecation in the public API served as a general notification of project direction,
maintaining compatibility with previous major version releases. Apache NiFi 2.9.0 included NiFi API 2.8.0, providing an
incremental step toward removal.
NIFI-15845 covered the removal of authorization for the Restricted
annotation from the framework, released in Apache NiFi 2.10.0. This removal of implementation also provided
compatibility with earlier versions, but eliminated the enforcement features. Although
NIFI-15847 removed usage of the Restricted annotation from
Processors and Controller Services within the project, final removal of the annotation from the public Apache NiFi API
is targeted for the next major release version.
Conclusion
The Restricted annotation in Apache NiFi provides a useful case study in secure system design. Although the initial motivations attempted to address a real concern, subsequent changes and vulnerabilities pointed to misalignment of declared security and actual security. Rather than perpetuate a partial solution, deprecating the feature for removal provided a better path forward. Redrawing the security boundary around the ability to change component configuration clarifies the extent of possible operations, avoiding misleading expectations.
The amount of extensibility in Apache NiFi creates an inherent tension between usability and security, highlighting the importance of clear boundaries. A coherent model is essential. With this background, solid lines of responsibility enhance system security and improve maintainability. Identifying potential dangers is critical, but sometimes accepting the risk and documenting the behavior is better than building a partial solution.