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.
DRY config and template system, easily extensible with Python
: Until aridity gets support for comments, you can use the colon directive to ignore data.
: Directives MUST be separated from data by whitespace, and are typically punctuation.
: Here's the equals directive:
foo = bar
: This does what you'd expect - assign the string value bar to foo.
: Observe that bar isn't quoted, values in aridity are normally barewords.
: foo is actually a path of length 1, path components are whitespace-separated:
this is a path = this is a value
: Any existing assignment can be overridden:
foo = baz
this is a path = this is different
: Internal whitespace in values is preserved (leading and trailing whitespace is not):
two sentences = Some like 2 spaces. After a full stop.
: You can use indentation to avoid typing a common path prefix multiple times:
app1 feature1
data1 = value1
data2 = value2
app2
feature1 data = value3
feature2
data1 = value4
data2 = value5
: Exactly the same effect without using indentation:
app1 feature1 data1 = value1
app1 feature1 data2 = value2
app2 feature1 data = value3
app2 feature2 data1 = value4
app2 feature2 data2 = value5
: The right hand side of an equals is actually an expression.
: In an expression, a dollar sign with brackets can be used to refer to another path:
has value
bar = $(foo)
value3 = $(app2 feature1 data)
: Round brackets and square brackets have exactly the same effect:
also has value bar = $[foo]
: Values can be concatenated:
two bars
without spacing = $(foo)$(foo)
with one space = $(foo) $(foo)
with 2 spaces = $(foo) $(foo)
: A few paths are predefined in every new context, such as:
home directory = $(~)
: To get a literal dollar there is a special form for quoting:
financial report = $'(We lost $100 on Friday.)
: Unlike in older versions, nested brackets (if any) do not end the special form early:
behaviour
expected = $'[Lunch cost $20 (worth it though).]
same = $'(Lunch cost $20 (worth it though).)
: Consequently, unbalanced brackets of the same kind as used by the special form must be avoided:
interval
lower = $'[The interval ][$'[0, 1) includes 0 but not 1.]
upper = $'(The interval )($'(0, 1] includes 1 but not 0.)
: Another special form can be used to preserve leading/trailing whitespace:
padded bars = $.( $(foo) $(foo) )
: Brackets can span multiple lines:
bar per line
without final newline = $.($(foo)
$(foo))
with final newline = $.($(foo)
$(foo)
)
: Evaluation is lazy, the expression is what is actually (and eagerly) assigned to the path:
no problem = $(this path will get a value later)
: If your use-case demands it, you can force eager evaluation:
bar even if foo changes later := $(foo)
: When evaluating a path the local scope is examined first, then its parents if path not found:
host
short path = nope
guest short path = yep
should be nope = $(short path)
guest should be yep = $(short path)
does not work = $(short path)
: Use the dot directive to include config from another file:
. /path/to/other/config.arid
: Thus you can factor out any config that's common to multiple deployments, and override as needed.
: It's possible (but maybe not so useful) to include under a non-trivial path:
other stuff . /path/to/other/config.arid
: There is no default context for relative paths, you must set cwd up-front as inclusion is not lazy:
cwd = /path/to
. other/config.arid
: Text between dollar and open bracket (that isn't a special form) is a function name.
: A useful function predefined in every new context is the platform slash:
path = $/($(~) Desktop report.txt)
: Unlike most functions, / can also be used (less legibly) as a value:
path = $(~)$(/)Desktop$(/)report.txt
: All functions are first class objects that can be assigned and overridden in the usual ways:
slash := $(/)
/ = something else
path = $slash($(~) Desktop report.txt)
: Simple lists can be created using the plus equals convenience directive.
: Indentation means you don't have to repeat the directive for every list element:
years +=
2018
2019
years += 2020
: A predefined join function takes a list and a separator and does what you'd expect:
copyright = $join($(years) $.(, ))
: Observe that functions typically take values not identifiers, so you have to 'get' explicitly.
: Lists are just a special case of nested scopes, which are much more powerful:
person
$.(The Guardians) year = 2018
Greta year = 2019
summary = Person of the Year was $join($map($(person) $.($label() in $(year))) $.(, )).
: Here the predefined label function gives you access to the last path component of a list element.
processtemplate app.json.aridt <config.arid >app.json
"
path is set to the most useful escape function for the target format
$"$(key)
is the same as $"($(key))
Print given config (with optional path in config) as shell snippet.
Interactive REPL.
Process the given template to stdout using config from stdin.
class ForeignScopeException(Exception)
The operation required a scope at precisely the given path.
class ConfigCtrl()
High level scope API.
@property
def r()
Get config object for reading, i.e. missing scopes will error.
@property
def w()
Get config object for writing, i.e. missing scopes will be created.
def loadappconfig(mainfunction,
moduleresource,
encoding='ascii',
settingsoptional=False)
Using app name as prefix load config from the given resource, apply user settings, and return config object for app. Context module for loading resource and the app name are deduced from mainfunction
, or these can be provided as a tuple. Set settingsoptional
to suppress the usual error if ~/.settings.arid does not exist.
def load(pathorstream)
Execute config from the given path or stream.
def execute(text)
Execute given config text.
def __iter__()
Yield keys and values.
def processtemplate(frompathorstream, topathorstream)
Evaluate expression from path/stream and write result to path/stream.
class RConfig(Parabject)
def __iter__()
Yield values only. Iterate over -self
for keys and values.
@_directive
class Colon()
Ignore rest of logical line.
@_directive
class Source()
Include path or resource at prefix.
@_directive
class Equals()
Assign expression to path.
@_directive
class ColonEquals()
Evaluate expression and assign result to path.
@_directive
class PlusEquals()
Assign expression to prefix plus an opaque key, i.e. add to list.
class Functions()
def screenstr(scope, resolvable)
GNU Screen string literal.
def scstr(scope, resolvable)
SuperCollider string literal.
def hclstr(scope, resolvable)
HashiCorp configuration language string literal.
def groovystr(scope, resolvable)
Groovy string literal.
def pystr(scope, resolvable)
Python literal.
def shstr(scope, resolvable)
Shell string literal.
def jsonquote(scope, resolvable)
JSON literal, also suitable for YAML.
def xmlattr(scope, resolvable)
XML attribute literal (including quotes).
def xmltext(scope, resolvable)
XML content, suggest assigning this to & with xmlattr assigned to " as is convention.
def tomlquote(scope, resolvable)
TOML string literal.
def urlquote(scope, resolvable)
Percent-encode all reserved characters.
def map(scope, objsresolvable, *args)
If given 1 arg, evaluate it against every scope in objsresolvable
and return that list.
If given 2 args, the first is a variable name to which each scope is temporarily assigned.
If given 3 args, the first two are variable names for scope key and scope respectively.
def join(scope, resolvables, *args)
Concatenate the given list, using optional separator. Frequently used with map
.
def str(scope, resolvable)
Coerce to string.
def list(scope, *resolvables)
Create a list.
@realname('try')
def try_(scope, *resolvables)
Attempt to evaluate each resolvable, returning the first that succeeds.
@realname('./')
def hereslash(scope, *resolvables)
Join the given path components with the directory of the current resource.
def readfile(scope, resolvable)
Include the content of the given path.
def processtemplate(scope, resolvable)
Evaluate the content of the given path as an expression.
def pyref(scope, moduleresolvable, qualnameresolvable)
Python object in given module with given qualified name. Module may be relative to current resource, in which case assignment with :=
is normally necessary. Typically used to import functions.
def pyres(scope, packageresolvable, nameresolvable, encoding=Text('ascii'))
Python resource for inclusion with .
directive.
def gpg(scope, resolvable)
Use gpg to decrypt the given base64-encoded blob.
class Resolvable(Struct)
def resolve(scope)
Evaluate this expression against the given scope.
def wrap(value)
Attempt to wrap the given value in a model object of the most specific type.
class AbstractScope(Resolvable)
def resolved(*path, **kwargs)
Follow the given path to get an expression, evaluate it (resolving any paths it requires, recursively), and return the resulting model object.
class Slash(Text, Function)
As text, the platform slash. As function, join args using that slash, starting with the last absolute path (or using all args if all relative).
def openresource(package_or_name, resource_name, encoding='ascii')
Like pkg_resources.resource_stream
but text mode.
def solo(v)
Assert exactly one object in the given sequence and return it.
def register(obj, paracls)
Instantiate paracls, set obj
to be the regular object associated with the new parabject, and return the parabject.
def dereference(parabject)
Get the regular object associated with parabject
or raise UnknownParabjectException.
class Parabject(object)
Subclasses typically implement __getattr__
for dynamic behaviour on attribute access.
def __neg__()
Dereference this parabject.
FAQs
DRY config and template system, easily extensible with Python
We found that aridity 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.