Summary
An authorization bypass in OPNsense can mishandle directly assigned comma-separated privileges when checking the user-config-readonly restriction. A user with both a component write privilege and the read-only privilege may be able to persist configuration changes through protected MVC APIs.
An authorization bypass in OPNsense can mishandle directly assigned comma-separated privileges when checking the user-config-readonly restriction. A user with both a component write privilege and the read-only privilege may be able to persist configuration changes through protected MVC APIs.
Affected context
The issue affects OPNsense deployments using the affected ACL privilege-checking path for MVC APIs. It occurs when privileges are assigned directly to a user as a comma-separated value and the user has both a component-specific write privilege and user-config-readonly; group-assigned privileges follow a different parsing path and are not affected by this specific flaw.
The issue affects OPNsense deployments using the affected ACL privilege-checking path for MVC APIs. It occurs when privileges are assigned directly to a user as a comma-separated value and the user has both a component-specific write privilege and user-config-readonly; group-assigned privileges follow a different parsing path and are not affected by this specific flaw.
Exploit preconditions
- Attack surface: OPNsense MVC APIs protected by read-only authorization checks
- Required access: An authenticated user account with directly assigned privileges
- Required privilege state: The account has both a component write privilege and user-config-readonly
- Trigger point: Authorization evaluation performed by ACL::hasPrivilege() before configuration persistence
- Why exploitation is possible: The directly assigned privilege string is treated as one value instead of being split into individual privileges, causing the exact read-only comparison to produce an incorrect result
- Attack surface: OPNsense MVC APIs protected by read-only authorization checks
- Required access: An authenticated user account with directly assigned privileges
- Required privilege state: The account has both a component write privilege and user-config-readonly
- Trigger point: Authorization evaluation performed by ACL::hasPrivilege() before configuration persistence
- Why exploitation is possible: The directly assigned privilege string is treated as one value instead of being split into individual privileges, causing the exact read-only comparison to produce an incorrect result
Why this happens
The underlying defect is inconsistent parsing of privilege lists between direct user assignments and group assignments. Directly assigned comma-separated privileges are appended and compared as a single string, so the authorization logic may fail to recognize user-config-readonly when it is combined with another privilege. This maps to CWE-863: Incorrect Authorization, because a protected operation can be permitted when the effective authorization state is evaluated incorrectly.
The underlying defect is inconsistent parsing of privilege lists between direct user assignments and group assignments. Directly assigned comma-separated privileges are appended and compared as a single string, so the authorization logic may fail to recognize user-config-readonly when it is combined with another privilege. This maps to CWE-863: Incorrect Authorization, because a protected operation can be permitted when the effective authorization state is evaluated incorrectly.
Potential impact
- Users may modify configuration that should remain read-only
- Component-specific settings could be changed through protected MVC APIs
- Firewall, routing, or service behavior may be altered
- Unauthorized changes could weaken security controls or disrupt availability
- Configuration integrity and administrative oversight could be reduced
- Users may modify configuration that should remain read-only
- Component-specific settings could be changed through protected MVC APIs
- Firewall, routing, or service behavior may be altered
- Unauthorized changes could weaken security controls or disrupt availability
- Configuration integrity and administrative oversight could be reduced
General mitigation guidance
Mitigation generally focuses on making privilege parsing consistent and authorization decisions explicit.
Common defensive patterns include:
- Normalize and split all comma-separated privilege values before comparison
- Represent privileges as structured sets rather than concatenated strings
- Apply deny or read-only restrictions consistently across direct and group assignments
- Enforce authorization checks immediately before configuration persistence
- Use least-privilege roles and avoid granting write permissions where they are unnecessary
- Add regression tests for mixed direct privileges and protected API operations
- Treat authorization inputs as untrusted until normalized and validated
Mitigation generally focuses on making privilege parsing consistent and authorization decisions explicit.
Common defensive patterns include:
- Normalize and split all comma-separated privilege values before comparison
- Represent privileges as structured sets rather than concatenated strings
- Apply deny or read-only restrictions consistently across direct and group assignments
- Enforce authorization checks immediately before configuration persistence
- Use least-privilege roles and avoid granting write permissions where they are unnecessary
- Add regression tests for mixed direct privileges and protected API operations
- Treat authorization inputs as untrusted until normalized and validated
How teams detect issues like this
Organizations can look for this weakness through:
- Static analysis of privilege parsing and exact string-comparison logic
- Code review of authorization helpers handling comma-separated or serialized permissions
- Tests combining read-only restrictions with component-specific write privileges
- API authorization tests that verify denied changes cannot reach persistence layers
- Audit-log review for configuration changes made by accounts intended to be read-only
- Policy enforcement requiring centralized privilege normalization before access decisions
Automated security and code-review tools may help identify inconsistent parsing and authorization checks, but behavior-focused tests are important for confirming effective permissions.
Organizations can look for this weakness through:
- Static analysis of privilege parsing and exact string-comparison logic
- Code review of authorization helpers handling comma-separated or serialized permissions
- Tests combining read-only restrictions with component-specific write privileges
- API authorization tests that verify denied changes cannot reach persistence layers
- Audit-log review for configuration changes made by accounts intended to be read-only
- Policy enforcement requiring centralized privilege normalization before access decisions
Automated security and code-review tools may help identify inconsistent parsing and authorization checks, but behavior-focused tests are important for confirming effective permissions.

