Skip to main content

SecurityAction

Enum SecurityAction 

#[repr(u16)]
pub enum SecurityAction {
Show 18 variants Deny = 1, Demand = 2, Assert = 3, NonCasDemand = 4, LinkDemand = 5, InheritanceDemand = 6, RequestMinimum = 7, RequestOptional = 8, RequestRefuse = 9, PrejitGrant = 10, PrejitDeny = 11, NonCasLinkDemand = 12, NonCasInheritance = 13, LinkDemandChoice = 14, InheritanceDemandChoice = 15, DemandChoice = 16, PermitOnly = 17, Unknown(u16),
}
Expand description

Security actions that control when and how permissions are enforced in .NET assemblies.

Security actions define the enforcement semantics for declarative security attributes. Each action specifies when the CLR should check permissions and what happens when permission checks fail. These correspond directly to the SecurityAction enumeration in the .NET Framework and ECMA-335 specifications.

§Action Categories

§Runtime Actions

Actions that are checked during code execution:

  • Demand: Check all callers in the call stack
  • Assert: Skip permission checks for the asserted permission
  • Deny: Block access to the specified resource
  • PermitOnly: Allow only the specified permissions

Actions that are checked during JIT compilation:

§Assembly Request Actions (Legacy)

Actions used for assembly-level permission requests (obsolete in modern .NET):

§Examples

use dotscope::metadata::security::SecurityAction;

// Check if an action is runtime-enforced
fn is_runtime_action(action: SecurityAction) -> bool {
    matches!(action,
        SecurityAction::Demand |
        SecurityAction::Assert |
        SecurityAction::Deny |
        SecurityAction::PermitOnly
    )
}

// Check if an action is security-sensitive
fn is_security_sensitive(action: SecurityAction) -> bool {
    matches!(action,
        SecurityAction::Assert |           // Can bypass security
        SecurityAction::Deny |             // Can block access
        SecurityAction::PermitOnly         // Can restrict permissions
    )
}

§.NET Framework Evolution

  • .NET 1.0-3.5: All actions supported with full CAS enforcement
  • .NET 4.0: Security transparency model, some actions deprecated
  • .NET Core/5+: Most actions become no-ops, kept for compatibility

§ECMA-335 References

  • Partition II, Section 23.1.16: Security action enumeration values
  • Partition II, Section 22.11: DeclSecurity table structure
  • Partition I, Section 10: Security model overview

§Binary Representation

Security actions are stored as 16-bit unsigned integers in .NET metadata. The numeric values are defined by ECMA-335 and must remain stable for compatibility.

Variants§

§

Deny = 1

Denies access to the specified resources, overriding any grants.

When a Deny action is encountered, the CLR will refuse any demands for the specified permissions, regardless of whether the code has been granted those permissions. This is used to restrict access even when code would normally have the required permissions.

§Security Implications

  • Overrides permission grants, creating a “security hole” prevention mechanism
  • Useful for restricting untrusted code or creating security boundaries
  • Can prevent code from accessing sensitive resources even if granted permission

§Example Usage

[FileIOPermission(SecurityAction.Deny, Read = @"C:\Sensitive")]
public void RestrictedMethod() {
    // This method cannot read from C:\Sensitive even if normally allowed
}
§

Demand = 2

Demands that all callers in the call chain have the specified permission.

This action causes the CLR to perform a stack walk, checking that every caller in the call chain has been granted the specified permission. If any caller lacks the permission, a SecurityException is thrown.

§Security Implications

  • Most common security action for runtime permission checks
  • Ensures all code in the call stack is trusted for the operation
  • Can impact performance due to stack walking

§Example Usage

[FileIOPermission(SecurityAction.Demand, Read = @"C:\Data")]
public void ReadSensitiveFile() {
    // All callers must have read permission for C:\Data
}
§

Assert = 3

Asserts that the specified permission should be granted without further checks.

When code asserts a permission, subsequent demands for that permission will succeed without performing a stack walk beyond the asserting frame. This effectively “shields” callers from needing the asserted permission.

§Security Implications

  • Bypasses normal security checks, creating potential security risks
  • Should only be used by highly trusted code
  • Can create privilege escalation if misused
  • Requires SecurityPermission with Assertion flag to use

§Example Usage

[FileIOPermission(SecurityAction.Assert, Read = @"C:\SystemData")]
public void TrustedSystemOperation() {
    // This method can read system data regardless of caller permissions
}
§

NonCasDemand = 4

Demands that the current assembly has been granted the specified permission.

This action checks that the currently executing assembly has the required permission, but does not perform a stack walk to check callers. It is used for permissions that are not part of the Code Access Security (CAS) system.

§Security Implications

  • Only checks the immediate assembly, not the entire call stack
  • Used for permissions outside the traditional CAS model
  • Less expensive than full stack walking demands

§Example Usage

[MyCustomPermission(SecurityAction.NonCasDemand, Value = "required")]
public void NonCasSecuredMethod() {
    // Only this assembly needs the custom permission
}
§

LinkDemand = 5

Demands that the immediate caller has been granted the specified permission.

Link demands are checked at JIT compilation time rather than runtime. They verify that the immediate caller (not the entire call stack) has the required permission. This provides security with better performance than runtime demands.

§Security Implications

  • Checked at JIT time, not runtime, for better performance
  • Only checks immediate caller, potentially less secure than full stack walk
  • Can be bypassed by reflection in some scenarios

§Example Usage

[FileIOPermission(SecurityAction.LinkDemand, Unrestricted = true)]
public void FileOperationMethod() {
    // Immediate caller must have unrestricted file access
}
§

InheritanceDemand = 6

Demands that classes inheriting from or overriding this method have the specified permission.

This action ensures that any code that derives from a class or overrides a method has the required permission. It is checked when the derived class is loaded or when the override is JIT compiled.

§Security Implications

  • Protects against malicious inheritance or method overriding
  • Checked at class loading or method compilation time
  • Ensures derived classes maintain security requirements

§Example Usage

[SecurityPermission(SecurityAction.InheritanceDemand, ControlPrincipal = true)]
public virtual void SecuritySensitiveMethod() {
    // Classes inheriting this must have ControlPrincipal permission
}
§

RequestMinimum = 7

Specifies the minimum permissions required for the assembly to run (legacy).

This action was used in early .NET versions to specify the minimum set of permissions that an assembly required to function. It is now obsolete and ignored in modern .NET implementations, but remains for compatibility with older assemblies.

§Legacy Status

  • Obsolete in .NET Framework 4.0 and later
  • Ignored by modern .NET runtimes
  • Maintained for compatibility with older assemblies

§Example Usage (Legacy)

[assembly: FileIOPermission(SecurityAction.RequestMinimum, Unrestricted = true)]
// Assembly requests minimum file I/O permissions
§

RequestOptional = 8

Specifies optional permissions that would be beneficial for the assembly (legacy).

This action was used to specify permissions that an assembly could use if available, but could function without. Like RequestMinimum, it is now obsolete and ignored in modern .NET implementations.

§Legacy Status

  • Obsolete in .NET Framework 4.0 and later
  • Ignored by modern .NET runtimes
  • Assembly would receive these permissions if security policy allowed

§Example Usage (Legacy)

[assembly: RegistryPermission(SecurityAction.RequestOptional, Unrestricted = true)]
// Assembly would like registry access if possible
§

RequestRefuse = 9

Specifies permissions that the assembly explicitly refuses (legacy).

This action was used to specify permissions that an assembly explicitly did not want to be granted, even if security policy would normally grant them. This provided a way for assemblies to limit their own privileges.

§Legacy Status

  • Obsolete in .NET Framework 4.0 and later
  • Ignored by modern .NET runtimes
  • Was used for defense-in-depth security practices

§Example Usage (Legacy)

[assembly: FileIOPermission(SecurityAction.RequestRefuse, Unrestricted = true)]
// Assembly explicitly refuses all file I/O permissions
§

PrejitGrant = 10

Reserved for pre-JIT compilation grants (implementation-specific).

This action is used internally by the .NET runtime during ahead-of-time (AOT) compilation scenarios. It is not intended for use in user code and represents permissions that should be granted during pre-compilation.

§Implementation Details

  • Used internally by runtime pre-compilation systems
  • Not for use in application code
  • Related to Native Image Generator (ngen.exe) and similar tools
§

PrejitDeny = 11

Reserved for pre-JIT compilation denials (implementation-specific).

This action is used internally by the .NET runtime during ahead-of-time (AOT) compilation scenarios. It represents permissions that should be denied during pre-compilation.

§Implementation Details

  • Used internally by runtime pre-compilation systems
  • Not for use in application code
  • Related to Native Image Generator (ngen.exe) and similar tools
§

NonCasLinkDemand = 12

Link-time demand for non-CAS permissions.

Similar to LinkDemand, but for permissions that are not part of the traditional Code Access Security system. This provides JIT-time checking for custom permission types while maintaining the performance benefits of link-time verification.

§Security Implications

  • JIT-time checking for better performance
  • Only checks immediate caller
  • Used for custom permission types outside CAS

§Example Usage

[MyCustomPermission(SecurityAction.NonCasLinkDemand, Level = "High")]
public void CustomSecuredMethod() {
    // Immediate caller needs custom permission at JIT time
}
§

NonCasInheritance = 13

Inheritance demand for non-CAS permissions.

Similar to InheritanceDemand, but for permissions that are not part of the traditional Code Access Security system. This ensures that classes inheriting from or overriding this code have the required custom permissions.

§Security Implications

  • Protects inheritance chains with custom permissions
  • Checked at class loading or method compilation time
  • Used for custom permission types outside CAS

§Example Usage

[MyCustomPermission(SecurityAction.NonCasInheritance, Level = "High")]
public virtual void InheritanceProtectedMethod() {
    // Derived classes need custom permission
}
§

LinkDemandChoice = 14

Choice-based link demand for transparent code in .NET 4.0 security model.

This action is part of the .NET 4.0 security transparency model, where it allows transparent code to specify link demands. The “choice” aspect relates to the transparency model’s approach to security decisions.

§.NET 4.0 Security Transparency

  • Used in security-transparent assemblies
  • Part of the simplified security model introduced in .NET 4.0
  • Allows transparent code to participate in security decisions

§Example Usage

[FileIOPermission(SecurityAction.LinkDemandChoice, Unrestricted = true)]
public void TransparentLinkDemand() {
    // Transparent code can specify link demands
}
§

InheritanceDemandChoice = 15

Choice-based inheritance demand for transparent code in .NET 4.0 security model.

This action allows security-transparent code to specify inheritance demands as part of the .NET 4.0 security transparency model. It provides a way for transparent code to control inheritance security requirements.

§.NET 4.0 Security Transparency

  • Used in security-transparent assemblies
  • Allows transparent code to control inheritance security
  • Part of the simplified security model

§Example Usage

[SecurityPermission(SecurityAction.InheritanceDemandChoice, ControlPrincipal = true)]
public virtual void TransparentInheritanceDemand() {
    // Transparent code can specify inheritance demands
}
§

DemandChoice = 16

Choice-based demand for transparent code in .NET 4.0 security model.

This action allows security-transparent code to specify runtime demands as part of the .NET 4.0 security transparency model. It enables transparent code to participate in runtime security decisions with explicit choice semantics.

§.NET 4.0 Security Transparency

  • Used in security-transparent assemblies
  • Allows transparent code to make runtime security demands
  • Part of the choice-based security model

§Example Usage

[FileIOPermission(SecurityAction.DemandChoice, Read = @"C:\Data")]
public void TransparentDemand() {
    // Transparent code can specify runtime demands
}
§

PermitOnly = 17

Restricts code to only the specified permissions, denying all others.

When a PermitOnly action is encountered, the CLR restricts the code to only the permissions specified, effectively denying all other permissions even if they were previously granted. This creates a privilege restriction mechanism.

§Security Implications

  • Reduces the effective permission set of code
  • Useful for creating security boundaries within trusted code
  • Can prevent code from using permissions it was granted
  • Complements Deny by allowing only specific permissions

§Example Usage

[FileIOPermission(SecurityAction.PermitOnly, Read = @"C:\SafeData")]
public void RestrictedFileOperation() {
    // This method can only read from C:\SafeData, no other file operations
}
§

Unknown(u16)

Unknown security action.

Trait Implementations§

§

impl Clone for SecurityAction

§

fn clone(&self) -> SecurityAction

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
§

impl Copy for SecurityAction

§

impl Debug for SecurityAction

§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
§

impl Display for SecurityAction

§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
§

impl Eq for SecurityAction

§

impl From<SecurityAction> for u16

§

fn from(action: SecurityAction) -> Self

Converts to this type from the input type.
§

impl From<u16> for SecurityAction

§

fn from(value: u16) -> Self

Converts to this type from the input type.
§

impl PartialEq for SecurityAction

§

fn eq(&self, other: &SecurityAction) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
§

impl StructuralPartialEq for SecurityAction

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> AsAny for T
where T: Any,

Source§

fn as_any(&self) -> &(dyn Any + 'static)

Source§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Source§

fn type_name(&self) -> &'static str

Gets the type name of self
Source§

impl<T> Boilerplate for T
where T: Copy + Send + Sync + Debug + PartialEq + 'static,

Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> Downcast for T
where T: AsAny + ?Sized,

Source§

fn is<T>(&self) -> bool
where T: AsAny,

Returns true if the boxed type is the same as T. Read more
Source§

fn downcast_ref<T>(&self) -> Option<&T>
where T: AsAny,

Forward to the method defined on the type Any.
Source§

fn downcast_mut<T>(&mut self) -> Option<&mut T>
where T: AsAny,

Forward to the method defined on the type Any.
Source§

impl<T> DynClone for T
where T: Clone,

Source§

fn __clone_box(&self, _: Private) -> *mut ()

Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
Source§

impl<T> ErasedDestructor for T
where T: 'static,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, A> IntoAst<A> for T
where T: Into<A>, A: Ast,

Source§

fn into_ast(self, _a: &A) -> A

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<F, T> IntoSample<T> for F
where T: FromSample<F>,

Source§

fn into_sample(self) -> T

Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> Scalar for T
where T: 'static + Clone + PartialEq + Debug,

Source§

impl<SS, SP> SupersetOf<SS> for SP
where SS: SubsetOf<SP>,

Source§

fn to_subset(&self) -> Option<SS>

The inverse inclusion map: attempts to construct self from the equivalent element of its superset. Read more
Source§

fn is_in_subset(&self) -> bool

Checks if self is actually part of its subset T (and can be converted to it).
Source§

fn to_subset_unchecked(&self) -> SS

Use with care! Same as self.to_subset but without any property checks. Always succeeds.
Source§

fn from_subset(element: &SS) -> SP

The inclusion map: converts self to the equivalent element of its superset.
Source§

impl<T> ToCompactString for T
where T: Display,

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
Source§

impl<T> TryClone for T
where T: Clone,

Source§

fn try_clone(&self) -> Result<T, Error>

Clones self, possibly returning an error.
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more