Research
Security News
Malicious npm Packages Inject SSH Backdoors via Typosquatted Libraries
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
A clean, simple framework for automatically injecting dependencies into objects and functions based around Python's type-hinting system. The framework provides caching of injectable objects, though this may be disabled on a class-by-class basis. It also supports managing independent caches for different contexts.
# Easy mode
from autoinject import injector
@injector.injectable
class MyInjectableClass:
# __init__() should have no additional required arguments
def __init__(self):
pass
# Hard mode, must specify the fully-qualified name of the class,
# but gain control over the arguments
@injector.register("example.MyInjectableClass", os.environ("MY_CONFIG_FILE"))
class MyInjectableClass:
def __init__(self, config_file):
# we receive os.environ("MY_CONFIG_FILE") as config_file here
# positional and keyword arguments to @injector.register() are supported
pass
# Decorate with @injector.inject for functions/methods:
@injector.inject
def inject_me(param1, param2, injected_param: MyInjectableClass):
# injected_param is set to an instance of MyInjectableClass
pass
# Omit the injected parameters when calling it:
inject_me("arg1", "arg2")
# For classes, use @injector.construct to set instance attributes
# based on the class attributes
class InjectMe:
injected_attribute: MyInjectableClass = None
@injector.construct
def __init__(self):
# self.injected_attribute is set to an instance of MyInjectableClass
pass
# No need to do anything special here:
obj = InjectMe()
# obj.injected_attribute is set by the decorator before __init__() is called.
You can override injected classes in your unit tests using the @injector.test_case()
decorator. This provides an
independent global context within the test case function and allows you to pass a map of objects to inject. For example,
from autoinject import injector
# Your injectable original class
@injector.injectable_global
class ServiceConnection:
def execute(self) -> int:
# Real connection code here, returns HTTP status code
pass
# The class you want to write a test case for that uses the injectable class.
class UsesServiceConnection:
connection: ServiceConnection = None
@injector.construct
def __init__(self):
pass
def test_me(self) -> bool:
# Super simple, check if response code is under 400
resp_code = self.connection.execute()
return resp_code < 400
# Testing stuff
import unittest
# Stub for testing
class _StubServiceFixture:
def __init__(self, response_code):
self.response_code = response_code
def execute(self) -> int:
return self.response_code
# Test case
class TestUsesServiceConnection(unittest.TestCase):
@injector.test_case({
ServiceConnection: _StubServiceFixture(200)
})
def test_success_200(self):
test_obj = UsesServiceConnection() # this will use the injected objects now
self.assertTrue(test_obj.test_me())
@injector.test_case({
ServiceConnection: _StubServiceFixture(400)
})
def test_failure_400(self):
test_obj = UsesServiceConnection()
self.assertFalse(test_obj.test_me())
Read the full documentation for more details.
inspect.getmembers()
when the
same class is created many times. This results in significant speed increases.@injector.test_case()
decorator is available for use with unit testing frameworks. It executes the decorated
function with a different global and non-global context to ensure the independence of test functions. In addition, one
can override the injected classes to provide specific test fixtures. These are passed as a dict of either type
objects
or fully qualified class names as strings as keys and either the type
or class name as string (to create the object),
or an object or function to use as the injected object.@injector.inject
, so both are not needed.
@injector.with_contextvars
: Creates a new context that is a copy of the current one@injector.with_same_contextvars
: Uses the current context@injector.with_empty_contextvars
: Creates a new empty contextwith_contextvars
wrapper, you can inject the context object using type-hinting (e.g.
ctx: contextvars.Context
). Note that this is actually an instance of ContextVarsManager
which is a context manager
that delegates most functionality to the current contextvars.Context
object with a few modifications:
set(context_var, value) -> token
and the complementary reset(context_var, token)
to
handle variable setting and resetting within the context manager.
context_var
ctx.run(context_var.METHOD, *args, **kwargs)
.set()
and reset()
operations are performed in the context that the manager is
managing (since the manager doesn't run the inner block in the context).run()
will just directly call the function (it is in the current context essentially)copy()
is an alias for contextvars.copy_context()
set()
and reset()
make a copy of the current context and return the results of its
method. This copy is transient and remade each time, so modules making extensive use of it can call copy()
and
check the copy.threading.Thread.run()
methods to
ensure clean-up (@injector.as_thread_run()
). This also is a wrapper around @injector.inject
so you can inject
variables into your run()
method directly.__cleanup__()
method which will be invoked when the global cache or context
cache is cleared.__cleanup__()
IS NOT INVOKED for one-time use objects at the moment, but this is planned as a feature.entry_points(group=?)
was not supportedCONTEXT_CACHE
will now have separate instances within threadsinjector.get()
as a fast way to get the object that would be injected (useful if operating outside of
a function or method)injector.register_constructor()
as a wrapper to register a class in a non-decorated fashionautoinject.injectables
to directly register injectable classesautoinject.registrars
weight
keyword argument to register()
and register_construct()
to control overriding ordercleanup()
function in the ContextManager()
class which triggers informant objects to check for
old items that are no longer needed. This was added mostly to support the thread-based context informant, since it
has no easy way of calling destroy()
whenever the thread ends (unless one manually calls it). It is the best
practice if you can call destroy()
directly whenever a context ceases to exist instead of relying on cleanup()
.FAQs
Automated dependency injection for Python
We found that autoinject 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.
Research
Security News
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
Security News
MITRE's 2024 CWE Top 25 highlights critical software vulnerabilities like XSS, SQL Injection, and CSRF, reflecting shifts due to a refined ranking methodology.
Security News
In this segment of the Risky Business podcast, Feross Aboukhadijeh and Patrick Gray discuss the challenges of tracking malware discovered in open source softare.