Security News
Research
Data Theft Repackaged: A Case Study in Malicious Wrapper Packages on npm
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
Most object oriented languages (C++, Java, Dart, Kotlin, Swift) include visibiliy modifiers. This enables encapsulation where for example the inner workings of a class can be detached from the outside world and thus protected from direct modification.
Python on the other hand does not have a language-backed concept of privacy. Instead functions or variables with an identifier that starts with an underscore are deemed private and should not be modified or otherwise relied upon since they may change in a future version of the module.
In some cases, certain attributes may be crucial for the correct working a class and the programmer might want to pervent any inadvertent modification.
The package lockattrs
provides a decorator that can
be used with the method __setattr__
to lock certain attributes
or all attributes.
Note that despite the name similarity lockattrs
is
not related to the package attrs
providing
a concise way of creating and validating data classes.
To install the package lockattrs
use the command:
$ pip install lockattrs
This package provides the decorator function protect
which can be
used to prevent modification of attributes
after they have been initially set.
The intended use-case is demonstrated below. Locking the instance attributes of a meta-class is equivalent to locking the class attributes of the class (the meta-class instance).
Using the decorator protect
involves the following steps:
__setattr__
.__setattr__
with the function protect
.from lockattrs import protect
class AMeta(type):
"""
Meta class of A.
"""
@protect(('data','id'), )
def __setattr__(self, name: str, value: Any) -> None:
return super().__setattr__(name, value)
class A(metaclass=AMeta):
id = 'a01'
pass
A.id = 'b02' # Raises an error. Attribute 'id' is set and locked.
A.data = 'initial-data' # First initiation is OK. Attribute 'data' is now locked.
A.data = 'new-data' # Raises an error (default type: ProtectedAttributeError).
A.name = 'A'
A.name = 'A1' # OK, since the attribute 'name' is not locked.
The code below demonstrates how to use the decorator
function @protect
to lock certain attributes of a class instance.
from lockattrs import protect
class B():
"""
Sample class with locked attributes.
"""
id = 57
@protect(('data','id'), ) # To lock all attributes use: @protect()
def __setattr__(self, name: str, value: Any) -> None:
return super().__setattr__(name, value)
B.id = 28 # OK. Class attributes are not locked.
# To lock class attributes see section above.
# Creating an instance of B.
b = B()
b.id = 77 # Modification of the attribute 'id' via 'self' raises
# an error since the annotated method `__setattr__` is
# called.
b.data = 'initial-data' # First initiation is OK. Attribute 'data' is now locked.
b.data = 'new-data' # Raises an error (default type: ProtectedAttributeError).
b.name = 'b'
b.name = 'b1' # OK, since the attribute 'name' is not locked.
Note: Locking certain attributes may be prohibitively costly in terms of computational time when used with objects that are instantiated often (for example in a loop) and where attributes are set/modified frequently.
The benchmarks below were produced using the package
pytest-benchmark
on a PC with 32GB RAM
and an Intel Core i5-6260U CPU running at 1.80GHz.
As the mean runtimes show, setting an attribute of class A
takes approximately 40 times as long compared to a standard class
(without an annotated __setattr__
method).
--------------------------------- benchmark: 2 tests -----------------------------------
Name (time in ns) Mean StdDev Rounds Iterations
----------------------------------------------------------------------------------------
test_benchmark_set_attrs 348.8611 (1.0) 66.8829 (1.0) 4 20000
test_benchmark_set_attrs_A 13,496.0524 (38.69) 912.2178 (13.64) 4 20000
----------------------------------------------------------------------------------------
Please file feature requests and bugs at the issue tracker. Contributions are welcome.
FAQs
Decorator used to lock class attributes.
We found that lockattrs demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Research
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
Research
Security News
Attackers used a malicious npm package typosquatting a popular ESLint plugin to steal sensitive data, execute commands, and exploit developer systems.
Security News
The Ultralytics' PyPI Package was compromised four times in one weekend through GitHub Actions cache poisoning and failure to rotate previously compromised API tokens.