Container plugin stops relying upon `removed` notification for container engine SDKs too,
and always use the `procexit` logic.
The go-worker still has the ability to attach `removed` listeners,
but it's only used by worker test executable and go-worker tests now.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
Let the async event cleanup the cache for us.
This way, other plugins can get notified even when we are
removing a bpm/lxc container.
Also, bump plugin version to 0.3.5.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
Generate the compile commands by default, to improve the development
experience (e.g. with clangd)
Signed-off-by: Angelo Puglisi <angelopuglisi86@gmail.com>
Add initial `renameat` parsing and extraction support. The support
must be completed by updating the sinsp status leveraging the parsing
support.
Signed-off-by: Leonardo Di Giovanna <leonardodigiovanna1@gmail.com>
Reorganize code handling event parsing and field extraction
capabilities into separate functions.
Signed-off-by: Leonardo Di Giovanna <leonardodigiovanna1@gmail.com>
Replace usage of offsets with slices. This enables better compile-time
checks thanks to the native support for slice types.
In order to restore a previous auxbuf writer state, the user must
first cache its state using the `Writer::save()` and
`AuxiliaryBuffer::save_writer_state()` APIs; then it can restore it
using the `AuxiliaryBuffer::resume_writer()` API.
Moreover, make constants governing the auxbuf limits more precise,
and add documentation related to some auxbuf APIs.
Signed-off-by: Leonardo Di Giovanna <leonardodigiovanna1@gmail.com>
Remove unsafe code from `auxbuf` by using `zerocopy` crate to perform
conversions between bytes and structs as well as unaligned read and
write operations.
Signed-off-by: Leonardo Di Giovanna <leonardodigiovanna1@gmail.com>
Move data extraction logic out of auxbuf by providing a generic way
of storing fixed-length parameters and a generic way of storing
variable-length parameters. The two main helpers are
`auxbuf::Writer::store_fixed_len_param()` and
`auxbuf::Writer::store_var_len_param()`. Both these helpers
accept some sort of length parameters, allowing to reserve memory on
the buffer, and a `write_fn`, allowing to build the parameter content.
`write_fn` receives an `auxbuf::ParamWriter` as parameter: this
object allows to build the parameter content by providing a way to
write chunks of data.
The data extraction logic now resides in a separate
`operations::writer_helpers` module.
Signed-off-by: Leonardo Di Giovanna <leonardodigiovanna1@gmail.com>
Use a consistent order in `auxbuf` module code by listing the
private methods right after their usage.
Signed-off-by: Leonardo Di Giovanna <leonardodigiovanna1@gmail.com>
Introduce auxbuf writer abstraction to split data container from
business logic writing into them.
Signed-off-by: Leonardo Di Giovanna <leonardodigiovanna1@gmail.com>
Change the internal auxbuf methods' naming convention from using
`push*` to `write*`
Signed-off-by: Leonardo Di Giovanna <leonardodigiovanna1@gmail.com>
Replace "auxiliary map" with "auxiliary buffer", as the name fits
more its purpose.
Signed-off-by: Leonardo Di Giovanna <leonardodigiovanna1@gmail.com>
Replace unsafe ring buffer events parsing logic with safe one.
Signed-off-by: Leonardo Di Giovanna <leonardodigiovanna1@gmail.com>
Co-authored-by: Grzegorz Nosek <grzegorz.nosek@sysdig.com>
Instead of sending the entire auxiliary map buffer, send only data
the populated sub-part.
Signed-off-by: Leonardo Di Giovanna <leonardodigiovanna1@gmail.com>
Since the c string comes from a stack variable `.c_str()`,
and the go string will be used async, `ptr.GoString()` does not
guarantee that the string is kept alive for all its duration,
leading to bogus reads.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
Podman relies upon context to store its connection infos.
Using same ctx already used by the real Podman engine means that
we are going to tamper with its connection info stored in the main ctx.
Instead, fetcher should use its own context.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
Use a single map to save the state that operations share among
multiple programs. Using a single map has a lower impact on the system
memory wrt the approach leveraging a single map per operation.
A single program can save, for the current thread, some information
that wants to share with other programs aiming to collect data for a
given operation. Since a single thread, in a given moment, can only
execute a single operation, the shared information can be encoded
using enum and their variants, a single variant representing the info
of a single operation. Notice that variants are single-element tuple
struct: this decision was made to keep the data access more ergonomic.
Signed-off-by: Leonardo Di Giovanna <leonardodigiovanna1@gmail.com>
Enforce global coding style and policies by leveraging the
`pre-commit` framework. Move the `krsi` plugin's specific `pre-commit`
configuration in the root of the project, tweaking the `rustfmt.toml`
file to enforce the `rustfmt` tool's edition on a plugin-basis instead
of enforcing it globally in the `pre-commit` hook. Update the `krsi`
plugin's `README.md` to point to the new project's `README.md`
section.
Signed-off-by: Leonardo Di Giovanna <leonardodigiovanna1@gmail.com>
Add support for automatic generation of `krsi` plugin's field
extraction. Moreover, add support for handling multi-line field
extraction descriptions.
Signed-off-by: Leonardo Di Giovanna <leonardodigiovanna1@gmail.com>
Signed-off-by: Luca Guerra <luca@guerra.sh>
Signed-off-by: Leonardo Di Giovanna <leonardodigiovanna1@gmail.com>
Co-authored-by: Leonardo Di Giovanna <leonardodigiovanna1@gmail.com>
Provide support for `bind` syscall, as well as `IORING_OP_BIND`
io_uring operation. Even if provided, the support for the io_uring
operation is not enabled.
Signed-off-by: Leonardo Di Giovanna <leonardodigiovanna1@gmail.com>
Provide support for `renamat2`, `renameat` and `rename` syscalls, as
well as `IORING_OP_RENAMEAT` io_uring operation.
Signed-off-by: Leonardo Di Giovanna <leonardodigiovanna1@gmail.com>
Provide support for `mkdirat` and `mkdir` syscalls, as well as
`IORING_OP_MKDIRAT` io_uring operation.
Signed-off-by: Leonardo Di Giovanna <leonardodigiovanna1@gmail.com>
Provide support for `linkat` and `link` syscalls, as well as
`IORING_OP_LINKAT` io_uring operation.
Signed-off-by: Leonardo Di Giovanna <leonardodigiovanna1@gmail.com>
Provide support for `symlinkat` and `symlink` syscalls, as well as
`IORING_OP_SYMLINKAT` io_uring operation.
Signed-off-by: Leonardo Di Giovanna <leonardodigiovanna1@gmail.com>
Provide support for `socket` and `socketcall` syscalls, as well as
`IORING_OP_SOCKET` io_uring operation.
Signed-off-by: Leonardo Di Giovanna <leonardodigiovanna1@gmail.com>
Use a different path for tracking socket connection, removing the
need for monitoring sockets creation and for storing
`(sock_ptr, tgid) -> fd` associations.
Signed-off-by: Leonardo Di Giovanna <leonardodigiovanna1@gmail.com>
Ensure that `fd_install` invocations are handled only if the current
thread is trying to open a file: this means hooking at
`do_sys_openat2`'s entry and exit point to mark the file opening
procedure as started and finished.
Signed-off-by: Leonardo Di Giovanna <leonardodigiovanna1@gmail.com>
Set the number of `AUXILIARY_MAPS` entries to the number of
available CPUs. Moreover, reduce the size of each auxiliary map.
Signed-off-by: Leonardo Di Giovanna <leonardodigiovanna1@gmail.com>
Static-storage variables are correctly checked.
This can happend in 2 scenarios:
* sinsp erratingly calls multiple times start async API (should be a bug but better safe than sorry)
* Falco hot reload dry-run checks
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
Clone exit for the parent must already have correct cgroup for the child,
since we are not going to overwrite it in libs parsers.
Also, it makes sense.
Finally, added a test to check that listening CAP is correctly writing pod_uid.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
Implement the suggested output fields feature,
by suggesting `k8smeta.pod.name` and `k8smeta.ns.name` as output fields.
Also, entirely avoid the proc scan, instead relying on the listening CAPability to
initially loop over the thread table to attach pod_uid to threads.
`hostProc` initConfig key is now deprecated and unused.
Moved the plugin to 0.3.0 too.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
When building a shared library (.so) that contains CGO, it embeds its own instance of the Go runtime. When later the we dlopen that library from a Go program (which already has its own Go runtime) both copies of the runtime are loaded into the same process. Go’s runtime is designed to be a singleton, and having two instances leads to conflicts during the execution of the library’s global init functions, ultimately causing a segfault.
This error was noticed for the first time with the `container` plugin, which makes use of the Podman package, which in turn makes massive use of Go `init()` functions.
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
Some pre-ControlTower organization Cloutrail trails are missing the OrgId
in the AWSLogs S3 path. Making the OrgId optional gives them the option
to use S3AccountList.
Signed-off-by: Uli Heilmeier <uh@heilmeier.eu>
Signed-off-by: Francesco Pirrò <francesco.pirro@sysdig.com>
update(plugins/gcpaudit): bump plugin version to 0.5.0
Signed-off-by: Francesco Pirrò <francesco.pirro@sysdig.com>
chore(plugins/gcpaudit): update changelogs with v0.5.0 changes
Signed-off-by: Francesco Pirrò <francesco.pirro@sysdig.com>
add initial plugin structure
Signed-off-by: Igor Eulalio <igor.eulalio@sysdig.com>
add processor function, refactor workflow to leverage channels
Signed-off-by: Igor Eulalio <igor.eulalio@sysdig.com>
refactoring main function to handle Process in underlying package, introducing channels
Signed-off-by: Igor Eulalio <igor.eulalio@sysdig.com>
add makefile
Signed-off-by: Igor Eulalio <igor.eulalio@sysdig.com>
update regisry + readme for k8saudit-aks
Signed-off-by: Thomas Labarussias <issif+github@gadz.org>
add owners
Signed-off-by: Thomas Labarussias <issif+github@gadz.org>
fix Open method arg
Signed-off-by: Thomas Labarussias <issif+github@gadz.org>
refactor code to handle the channel logic, add Makefile helpers, add new rule
Signed-off-by: Igor Eulalio <igor.eulalio@sysdig.com>
add logs using proper plugin, finish configuration
Signed-off-by: Igor Eulalio <igor.eulalio@sysdig.com>
feat: add .envrc to gitignore
Signed-off-by: Igor Eulalio <igor.eulalio@sysdig.com>
feat: add .envrc to gitignore
Signed-off-by: Igor Eulalio <igor.eulalio@sysdig.com>
std::filesystem::directory_iterator works by retrieving entries on-the-fly as it iterates over them,
rather than preloading all entries. This implies that entries could indeed disappear (or appear)
between iterations, especially in highly dynamic directories such as /proc/.
The loop continues processing other entries even if an exception occurs,
allowing for robust and uninterrupted iteration.
Signed-off-by: Aldo Lacuku <aldo@lacuku.eu>
By scanning only /proc we missed the threads of a given process.
It scans all threads under a given process in /proc/pid/task.
Signed-off-by: Aldo Lacuku <aldo@lacuku.eu>
Signed-off-by: Thomas Labarussias <issif+github@gadz.org>
update the upload-artifact action version
Signed-off-by: Thomas Labarussias <issif+github@gadz.org>
Generalize our array length check. Use strings.TrimSuffix in order to
avoid a potential string under-read.
Signed-off-by: Gerald Combs <gerald@wireshark.org>
k8saudit-gke ships a rulesfiles that overrides the k8saudit rules. To make the
CI happy we have a symlink of the original k8saudit rules in k8saudit-gke/rules
directory. This commit filters out the symlinks when releasing the rulesfiles.
Signed-off-by: Aldo Lacuku <aldo@lacuku.eu>
Before adding an entry to the registry.yaml file we check that
the OCI artifact for that entry has been released.
Signed-off-by: Aldo Lacuku <aldo@lacuku.eu>
The Falco Bridge plugin of another tool is using the 'Display' value to have a
name for the field. => Adding 'Display' to all fields so that this plugin is usable.
Signed-off-by: Uli Heilmeier <uh@heilmeier.eu>
To speed up the process of getting all the keys, divide the inputParams
array into chunks and get the keys for each item in the chunk concurrently.
Signed-off-by: Uli Heilmeier <uh@heilmeier.eu>
When running the CI for a plugin which is set as an alternative
in the rules files, it is correctly set as a dependency.
Furthermore, the dependency extraction logic from rulesfiles
has been unified for all the use cases and supports multiple
rulesfiles at once.
Signed-off-by: Aldo Lacuku <aldo@lacuku.eu>
Support accounts for organization trails. When open parameter is
's3://bucket_name/prefix_name/AWSLogs/O-ID/' and 'S3AccountList' is not set
get all events for all accounts in the organization CloudTrail bucket.
If 'S3AccountList' is configured get events for the account IDs specified
in the comma separated list.
S3Interval also works for organisation trails.
Fixes: #423
Signed-off-by: Uli Heilmeier <uh@heilmeier.eu>
<!-- Thanks for sending a pull request! Here are some tips for you:
1. If this is your first time, please read our contributor guidelines in the [CONTRIBUTING.md](https://github.com/falcosecurity/.github/blob/master/CONTRIBUTING.md) file and learn how to compile Falco from source [here](https://falco.org/docs/source).
1. If this is your first time, please read our contributor guidelines in the [CONTRIBUTING.md](https://github.com/falcosecurity/.github/blob/main/CONTRIBUTING.md) file and learn how to compile Falco from source [here](https://falco.org/docs/source).
2. Please label this pull request according to what type of issue you are addressing.
3. Please add a release note!
4. If the PR is unfinished while opening it specify a wip in the title before the actual title, for example, "wip: my awesome feature"
Note: *The plugin system is a new feature introduced since Falco 0.31.0. You can find more detail in the original [proposal document](https://github.com/falcosecurity/falco/blob/master/proposals/20210501-plugin-system.md).*
This repository is the central hub for the Falco Plugin ecosystem. It serves two main purposes:
This repository contains the [Plugin Registry](#plugin-registry) and the [plugins officially maintained](#falcusecurity-plugins) by the Falcosecurity organization. [Plugins](https://falco.org/docs/plugins) can be used to extend [Falco](https://github.com/falcosecurity/falco) and of applications using [Falcosecurity libs](https://github.com/falcosecurity/libs). Please refer to the [official documentation](https://falco.org/docs/plugins) to better understand the plugin system's concepts and architecture.
- **Be a registry:** A comprehensive catalog of plugins recognized by The Falco Project, regardless of where their source code is hosted.
- **Monorepo for Falcosecurity plugins:** Official plugins hosted and maintained by The Falco Project, with robust release and distribution processes.
For more information about the plugin system’s architecture and concepts, please see the [official documentation](https://falco.org/docs/plugins).
---
## Plugin Registry
The Registry contains metadata and information about every plugin known and recognized by the Falcosecurity organization. It lists plugins hosted either in this repository or in other repositories. These plugins are developed for Falco and made available to the community. Check out the sections below to know how to [register your plugins](#registering-a-new-plugin) and see plugins currently contained in the registry.
The registry contains metadata and information about every plugin known and recognized by the Falcosecurity organization. It lists plugins hosted either in this repository or in other repositories. These plugins are developed for Falco and made available to the community.
### Registering a new Plugin
Registering your plugin inside the registry helps ensure that some technical constraints are respected, such as that a [given ID is used by exactly one plugin with event source capability](https://falco.org/docs/plugins/#plugin-event-ids) and allows plugin authors to [coordinate about event source formats](https://falco.org/docs/plugins/#plugin-event-sources-and-interoperability). Moreover, this is a great way to share your plugin project with the community and engage with it, thus gaining new users and **increasing its visibility**. We encourage you to register your plugin in this registry before publishing it. You can add your plugins in this registry regardless of where its source code is hosted (there's a `url` field for this specifically).
The registration process involves adding an entry about your plugin inside the [registry.yaml](./registry.yaml) file by creating a Pull Request in this repository. Please be mindful of a few constraints that are automatically checked and required for your plugin to be accepted:
- The `name` field is mandatory and must be **unique** across all the plugins in the registry
- *(Sourcing Capability Only)* The `id` field is mandatory and must be **unique** in the registry across all the plugins with event source capability
- The plugin `name` must match this [regular expression](https://en.wikipedia.org/wiki/Regular_expression): `^[a-z]+[a-z0-9-_\-]*$` (however, its not recommended to use `_` in the name, unless you are trying to match the name of a source or for particular reasons)
- The `source`*(Sourcing Capability Only)* and `sources`*(Extraction Capability Only)* must match this [regular expression](https://en.wikipedia.org/wiki/Regular_expression): `^[a-z]+[a-z0-9_]*$`
- The `url` field should point to the plugin source code
- The `rules_url` field should point to the default ruleset, if any
For reference, here's an example of an entry for a plugin with both event sourcing and field extraction capabilities:
| [dummy_c](https://github.com/falcosecurity/plugins/tree/master/plugins/dummy_c) | **Event Sourcing**<br/>ID: 4 <br/>`dummy_c` <br/>**Field Extraction** <br/>`dummy_c` | Like dummy, but written in C++ <br/><br/> Authors: [The Falco Authors](https://falco.org/community) <br/> License: Apache-2.0 |
| plugin-id-zero-value | **Event Sourcing**<br/>ID: 0 <br/>`` | This ID is reserved for particular purposes and cannot be registered. A plugin author should not use this ID unless specified by the documentation. <br/><br/> Authors: N/A <br/> License: N/A |
| test | **Event Sourcing**<br/>ID: 999 <br/>`test` | This ID is reserved for source plugin development. Any plugin author can use this ID, but authors can expect events from other developers with this ID. After development is complete, the author should request an actual ID <br/><br/> Authors: N/A <br/> License: N/A |
| test | **Event Sourcing**<br/>ID: 999 <br/>`test` | This ID is reserved for source plugin development. Any plugin author can use this ID, but authors can expect events from other developers with this ID. After development is complete, the author should request an actual ID <br/><br/> Authors: N/A <br/> License: N/A |
Another purpose of this repository is to host and maintain the plugins owned by the Falcosecurity organization. Each plugin is a standalone project and has its own directory, and they are all inside the [plugins](https://github.com/falcosecurity/plugins/tree/master/plugins) folder.
Along with the registry, this repository hosts the official plugins maintained by the Falcosecurity organization. Each plugin is an independent project with its own directory in the [plugins folder](https://github.com/falcosecurity/plugins/tree/main/plugins).
The `master` branch contains the most up-to-date state of development, and each plugin is regularly released. Please check our [Release Process](./release.md) to know how plugins are released and how artifacts are distributed. Dev builds are published each time a Pull Request gets merged into `master`, whereas stable builds are released and published only when a new release gets tagged. You can find the published artifacts at https://download.falco.org/?prefix=plugins.
The `main` branch reflects the latest development state, and plugins are released on a regular basis. Development builds are published automatically when a Pull Request is merged into `main`, while stable builds are released only when a new tag is created. You can find all published artifacts at [download.falco.org](https://download.falco.org/?prefix=plugins). For details on the release process, please see our [Release Process](./release.md).
If you wish to contribute your plugin to the Falcosecurity organization, you just need to open a Pull Request to add it inside the `plugins` folder and to add it inside the registry. In order to be hosted in this repository, plugins must be licensed under the [Apache 2.0 License](./LICENSE).
The instructions below explain how to install and apply only to plugins from this repository.
### Installing Plugins
Plugins hosted in this repository are built and distributed through Falco's official channels. You can easily install them using either [falcoctl](https://github.com/falcosecurity/falcoctl) or the [Falco Helm chart](https://github.com/falcosecurity/charts/tree/master/charts/falco).
#### Using falcoctl
1. **Install falcoctl:** If you haven't already, follow the [falcoctl installation guide](https://github.com/falcosecurity/falcoctl?tab=readme-ov-file#installation).
2. **Install a Plugin:** Execute the following command, replacing `<plugin-name>` with the name of the plugin you wish to install:
```bash
falcoctl index update falcosecurity
falcoctl artifact install <plugin-name>
```
> Depending on your environment, you may need to run the above commands with `sudo`.
3. Configure Falco to load the plugin as described in the [plugin's documentation](https://falco.org/docs/concepts/plugins/usage/#loading-plugins-in-falco).
#### Using the Falco Helm Chart
When installing Falco using the Helm chart, you can instruct the chart to install a specific plugin by setting the `falcoctl.config.artifact.install.refs` value and then adding the relevant plugin configuration under `falco`.
The Helm charts provides a preset [values-k8saudit.yaml](https://github.com/falcosecurity/charts/blob/master/charts/falco/values-k8saudit.yaml) file that can be used to install the `k8saudit` plugin or as example for installing other plugins.
## Contributing
If you want to help and wish to contribute, please review our [contribution guidelines](https://github.com/falcosecurity/.github/blob/master/CONTRIBUTING.md). Code contributions are always encouraged and welcome!
If you want to help and wish to contribute, please review our [contribution guidelines](https://github.com/falcosecurity/.github/blob/main/CONTRIBUTING.md). Code contributions are always encouraged and welcome!
If you wish to contribute a plugin to The Falco Project, simply open a Pull Request to add your plugin to the `/plugins` folder and [update the registry accordingly](./docs/registering-a-plugin.md). Note that to be hosted in this repository, plugins must be licensed under the [Apache 2.0 License](./LICENSE).
### Enforcing coding style and repo policies locally
This repository supports enforcing coding style and policies locally through the `pre-commit` framework. `pre-commit`
allows to automatically install `git-hooks` that will be executed at every new commit. The following is the list of
`git-hooks` defined in `.pre-commit-config.yaml` (notice that some of them only target files written in a specific
language):
1. the `rust-fmt` hook - a `pre-commit` git hook running `rust fmt` on the staged changes
2. the `dco` hook - a `pre-commit-msg` git hook running adding the `DCO` on the commit if not present
The following steps describe how to install these hooks.
##### Step 1
Install `pre-commit` framework following the [official documentation](https://pre-commit.com/#installation).
> __Please note__: you have to follow only the "Installation" section.
Using a unique `id` is mandatory to maintain interoperability across all plugins with _event sourcing_ capability. When a plugin is loaded by a compatible application (e.g., Falco), the `id` is used to route events to the correct plugin. Indeed, attempting to load two or more plugins using the same `id` will result in an error.
For this reason, The Falco Project maintains a [public registry of plugins](https://github.com/falcosecurity/plugins/blob/main/README.md#registering-a-new-plugin), which allows the assignment of a unique `id` for your plugin. However, some plugins may not be registered in the public registry. For example, if you are privately developing a plugin for your own use, you might use any `id` you want. To avoid conflicts in these situations, this document mandates general rules regarding `id` assignment and reservation.
## ID Blocks
The following ID ranges are designated for specific purposes:
| Block name | ID range | # of IDs | Description |
|---|---|---|---|
| Public | 0–1073741823 (30-bit) | 1073741824 | Used in the public registry. Single IDs in this range can be [assigned](#assigning-an-id) or [reserved](#reserving-an-id). |
| Private | 1073741824–2147483647 (30-bit) | 1073741824 | Used for private plugins (think of this range as the equivalent of 192.168.0.0/16 in networks). Organizations may use this range for plugins intended for their private domain. Interoperability is not guaranteed. |
| Reserved | 2147483648-3221225471 (30-bit) | 1073741824 | This range is reserved for future use and must not be used under any circumstances. |
| Internal | 3221225472-4294967295 (30-bit) | 1073741824 | This range is reserved for internal use and must not be used by plugins. It might be used by the plugin framework implementation for technical purposes. |
Notes:
- An `id` is a 32-bit unsigned integer. The MSBs are used to identify the block of IDs.
- Only IDs up to 1073741823 can be requested for use in the public registry.
- Only IDs up to 2147483647 can be used by plugins.
## Assigning an ID
The public registry is intended for assigning IDs to plugins that are publicly available. If you want to share your plugin with the community, you should follow the instructions reported in the [Registering a new plugin](../README.md#registering-a-new-plugin) section of this repository's documentation.
When making your request, please choose the next available ID in the [registry.yaml](../registry.yaml) file. The `id` will be definitively assigned to your plugin once the corresponding PR is merged, and the [registry.yaml](../registry.yaml) file is updated.
## Reserving an ID
For particular technical purposes or special cases, an `id` can be reserved so that it will not be assigned to any specific plugin. Notably, id 999 has been reserved for source plugin development. Any plugin author can temporarily use this `id`; however, it can't be assigned to any specific plugin and must not be used for purposes other than local development.
To reserve an `id`, you can use the same procedure for [registering a new plugin](../README.md#registering-a-new-plugin) and specify the `reserved: true` option.
Requests for `id` reservation will be evaluated on a case-by-case basis. The Falco Project reserves the right to reject any request for any reason.
Registering your plugin inside the registry helps ensure that some technical constraints are respected, such as that a [given ID is used by exactly one plugin with event source capability](https://falco.org/docs/concepts/plugins/architecture/#plugin-event-ids) and allows plugin authors to [coordinate about event source formats](https://falco.org/docs/concepts/plugins/architecture/#plugin-event-sources-and-interoperability). Moreover, this is a great way to share your plugin project with the community and engage with it, thus gaining new users and **increasing its visibility**. We encourage you to register your plugin in this registry before publishing it. You can add your plugins in this registry regardless of where its source code is hosted (there's a `url` field for this specifically).
The registration process involves adding an entry about your plugin inside the [registry.yaml](../registry.yaml) file by creating a Pull Request in this repository. Please be mindful of a few constraints that are automatically checked and required for your plugin to be accepted:
- The `name` field is mandatory and must be **unique** across all the plugins in the registry
- *(Sourcing Capability Only)* The `id` field is mandatory and must be **unique** in the registry across all the plugins with event source capability
- See [docs/plugin-ids.md](plugin-ids.md) for more information about plugin IDs
- The plugin `name` must match this [regular expression](https://en.wikipedia.org/wiki/Regular_expression): `^[a-z]+[a-z0-9-_\-]*$` (however, its not recommended to use `_` in the name, unless you are trying to match the name of a source or for particular reasons)
- The `source`*(Sourcing Capability Only)* and `sources`*(Extraction Capability Only)* must match this [regular expression](https://en.wikipedia.org/wiki/Regular_expression): `^[a-z]+[a-z0-9_]*$`
- The `url` field should point to the plugin source code
- The `rules_url` field should point to the default ruleset, if any
For reference, here's an example of an entry for a plugin with both event sourcing and field extraction capabilities:
* [`79c085e`](https://github.com/falcosecurity/plugins/commit/79c085e) update(anomalydetection): helper new filtercheck / output field anomaly.falco...
* [`489ef6d`](https://github.com/falcosecurity/plugins/commit/489ef6d) update(anomalydetection): ability to reset data structures w/ timers
* [`d4e72b8`](https://github.com/falcosecurity/plugins/commit/d4e72b8) update(anomalydetection): more usage safeguards and info log messages
* [`23bf05e`](https://github.com/falcosecurity/plugins/commit/23bf05e) update(anomalydetection): add some fallbacks / evt param extraction in cases ...
**This plugin is experimental and under development**
This `anomalydetection` plugin has been created upon this [Proposal](https://github.com/falcosecurity/falco/blob/master/proposals/20230620-anomaly-detection-framework.md).
## Introduction
The `anomalydetection` plugin enhances {syscall} event analysis by incorporating anomaly detection estimates for probabilistic filtering.
### Functionality
The initial scope focuses exclusively on "CountMinSketch Powered Probabilistic Counting and Filtering" for a subset of syscalls and a selection of options for defining behavior profiles. This limitation is due to current restrictions related to the plugin API and SDK layout.
The new framework primarily aims to improve the usability of standard Falco rules. It may reduce the need for precise rule tuning, leverages probabilistic count estimates to auto-tune noisy rules on the fly, and enables the creation of broader Falco rules. Read more in the [Proposal](https://github.com/falcosecurity/falco/blob/master/proposals/20230620-anomaly-detection-framework.md).
### TL;DR
The official documentation will eventually be available on the Falco [Plugins](https://falco.org/docs/plugins/) site. Therefore, consider this README as not being a complete documentation for using this plugin.
*Disclaimer*: Anomaly detection can mean different things to different people. It's best to keep your expectations low for this plugin's current capabilities. For now, it is focused solely on probabilistic counting.
What this plugin is:
- **Initial step for real-time anomaly detection in Falco**: Introduces basic real-time anomaly detection methods on the host.
- **Probabilistic counting**: Currently supports only probabilistic counting, with the guarantee that any overcounting remains within an acceptable error margin.
- **Use-case dependent**: Requires careful derivation of custom use cases; no default use cases are provided at this time.
- **Limited by current API**: Subject to several restrictions due to plugin API and other limitations.
- **Built for future extensibility**: Designed to support more algorithms in the future, limited to those that can be implemented in a single data pass to ensure real-time performance.
- **Documentation is insufficient**: Expect to need hands-on exploration to understand usage and restrictions.
What this plugin is not:
- **Not a pre-trained AI/ML model**.
- **Not ready out-of-the-box**: No default configuration or use cases are provided at this time.
- **Not a universal solution**: Does not offer a one-size-fits-all approach to anomaly detection.
- **No multi-pass algorithms**: Algorithms requiring multiple data passes are not planned; the plugin is intended to remain real-time and efficient for applicable use cases.
- **Not yet battle-tested in production**.
### Outlook
In the near term, the plan is to expand the syscalls for which behavior profiles can be applied and to enhance the fields available for defining these profiles. The first version is quite restrictive in this regard due to current plugin API limitations. Additionally, from an algorithmic and capabilities point of view, we will explore the following:
- Support for HyperLogLog probabilistic distinct counting (ETA unknown).
- Overcoming the cold start problem by loading sketch data structures and counts from previous agent runs or from test environments (ETA unknown).
- Efficient and feasible options for real-time, single-pass time series analysis (ETA unknown).
### Plugin Official Name
`anomalydetection`
## Capabilities
The `anomalydetection` plugin implements 2 capabilities:
* `extraction`
* `parsing`
## Supported Fields
Here is the current set of output / filter fields introduced by this plugin:
| `anomaly.count_min_sketch` | `uint64` | Index | Count Min Sketch Estimate according to the specified behavior profile for a predefined set of {syscalls} events. Access different behavior profiles/sketches using indices. For instance, anomaly.count_min_sketch[0] retrieves the first behavior profile defined in the plugins' `init_config`. |
| `anomaly.count_min_sketch.profile` | `string` | Index | Concatenated string according to the specified behavior profile (not preserving original order). Access different behavior profiles using indices. For instance, anomaly.count_min_sketch.profile[0] retrieves the first behavior profile defined in the plugins' `init_config`. |
| `anomaly.falco.duration_ns` | `uint64` | None | Falco agent run duration in nanoseconds, which could be useful for ignoring some rare events at launch time while Falco is just starting to build up the counts in the sketch data structures (if applicable). |
<!-- /README-PLUGIN-FIELDS -->
## Usage
**Configuration**
Here's an example of configuration of `falco.yaml`:
```yaml
plugins:
- name: anomalydetection
library_path: libanomalydetection.so
init_config:
count_min_sketch:
enabled: true
n_sketches: 3
# `gamma_eps`: auto-calculate rows and cols; usage: [[gamma, eps], ...];
# gamma -> error probability -> determine d / rows / number of hash functions
# eps -> relative error -> determine w / cols / number of buckets
gamma_eps: [
[0.001, 0.0001],
[0.001, 0.0001],
[0.001, 0.0001]
]
# `rows_cols`: pass explicit dimensions, supersedes `gamma_eps`; usage: [[7, 27183], ...]; by default disabled when not used.
# optional config `reset_timer_ms`, resets the data structure every x milliseconds, here one hour as example
# Remove JSON key if not wanted / needed.
"reset_timer_ms": 3600000
}
]
load_plugins: [anomalydetection]
```
The first version is quite restrictive with respect to the behavior profile's `event_codes` and `fields`. In a nutshell, you can currently define them only for a handful of event codes that Falco supports and a subset of the [Supported Fields for Conditions and Outputs](https://falco.org/docs/reference/rules/supported-fields/).
When you disable the `count_min_sketch` algorithm as shown below, all `anomaly.count_min_sketch` fields will be null.
```
count_min_sketch:
enabled: false
```
__NOTE__: Do not toggle the `enabled` key while hot reloading the config, as it currently does not get properly applied in such cases. Restart Falco with the `count_min_sketch` either enabled or disabled; subsequent reloads will work as expected.
**Behavior profiles for "execve/execveat/clone/clone3" events**
Example 1:
```
"event_codes": [293, 331],
```
Example 2:
```
"event_codes": [223, 335],
```
You can reference a behavior profile based on "execve/execveat/clone/clone3" events in any Falco rule that monitors any supported syscall. This works because every syscall is associated with a process.
**Behavior profiles for "fd-related" events**
Example 1:
```
rule: (evt.type in (open, openat, openat2) and evt.dir=<)
...
"event_codes": [3, 307, 327],
```
Example 2:
```
rule: (evt.type=connect and evt.dir=<)
...
"event_codes": [23],
```
You should avoid writing rules for arbitrary syscalls using "fd-related" behavior profiles because if a syscall doesn't involve a file descriptor (fd), referencing counts that rely on fd fields won't be meaningful.
Here's how it works:
- If your behavior profile includes `%fd.*` fields, all event codes in that profile must be related to file descriptors.
- If you use an "fd-related" behavior profile with a syscall that doesn't involve a file descriptor, the count will always be zero. While Falco won't crash, the anomaly detection estimate won't function as expected.
References:
- See the [Supported PPME `event codes`](#ppme-event-codes) reference below.
- See the [Supported Behavior Profiles `fields`](#behavior-profiles-fields) reference below.
**Open Parameters**:
This plugin does not have open params.
**Rules**
This plugin does not provide any default use cases or rules at the moment. More concrete use cases may be added at a later time.
Example of a dummy Falco rule using the `anomalydetection` fields for local testing:
```yaml
- macro: spawned_process
condition: (evt.type in (execve, execveat) and evt.dir=<)
- rule: execve count_min_sketch test
desc: "execve count_min_sketch test"
condition: spawned_process and proc.name=cat and anomaly.count_min_sketch[0] > 10
__NOTE__: Ensure you regularly execute `cat` commands. Once you have done so frequently enough, logs will start to appear. Alternatively, perform an inverse test to observe how quickly a very noisy rule gets silenced.
**Adoption**
To adopt the plugin framework, you can start by identifying rules in the [default](https://github.com/falcosecurity/rules) Falco ruleset that could benefit from auto-tuning based on your heuristics regarding counts. For example, you might broaden the scope of a rule and add an `anomaly.count_min_sketch` filter condition as a safety upper bound.
For initial adoption, we recommend creating new, separate rules inspired by existing upstream rules, rather than modifying rules that are already performing well in production.
Another approach is to duplicate a rule -- one version with and another without the anomaly detection filtering.
Alternatively, you can add the count estimates as output fields to provide additional forensic evidence without using the counts for on-host filtering.
Lastly, keep in mind that there is a configuration to reset the counts per behavior profile every x milliseconds if this suits your use case better.
### Running
This plugin requires Falco with version >= **0.38.2**.
1. Have Falco >= **0.38.2** installed and set up
2. Download the plugin's shared object (or build it yourself; see instructions below) and place it under `/usr/share/falco/plugins/libanomalydetection.so`
3. Modify the `falco.yaml` with the provided example [configuration](#configuration) above
4. Add a rule that uses `anomaly.count_min_sketch` as an output field and/or filter to `falco_rules.yaml`, and you're ready to go!
```shell
# Read the steps above before running Falco with this plugin
Read this [blog post](https://falco.org/blog/adaptive-syscalls-selection/) to learn more about Falco's internal PPME event codes compared to the syscall names you are used to using in Falco rules.
The list below is complete, and no other event codes from Falco can be used for the behavior profiles at the moment. The binary will error out if used incorrectly. Thank you for your patience.
```CPP
typedef enum {
PPME_SYSCALL_OPEN_X = 3, // compare to "(evt.type=open and evt.dir=<)" in a Falco rule
PPME_SOCKET_CONNECT_X = 23, // compare to "(evt.type=connect and evt.dir=<)" in a Falco rule
PPME_SYSCALL_CREAT_X = 59, // compare to "(evt.type=creat and evt.dir=<)" in a Falco rule
PPME_SYSCALL_CLONE_20_X = 223, // compare to "(evt.type=clone and evt.dir=<)" in a Falco rule
PPME_SOCKET_ACCEPT_5_X = 247, // compare to "(evt.type=accept and evt.dir=<)" in a Falco rule
PPME_SYSCALL_EXECVE_19_X = 293, // compare to "(evt.type=execve and evt.dir=<)" in a Falco rule
PPME_SYSCALL_OPENAT_2_X = 307, // compare to "(evt.type=openat and evt.dir=<)" in a Falco rule
PPME_SYSCALL_OPENAT2_X = 327, // compare to "(evt.type=openat2 and evt.dir=<)" in a Falco rule
PPME_SYSCALL_EXECVEAT_X = 331, // compare to "(evt.type=execveat and evt.dir=<)" in a Falco rule
PPME_SYSCALL_CLONE3_X = 335, // compare to "(evt.type=clone3 and evt.dir=<)" in a Falco rule
PPME_SYSCALL_OPEN_BY_HANDLE_AT_X = 337, // compare to "(evt.type=open_by_handle_at and evt.dir=<)" in a Falco rule
PPME_SOCKET_ACCEPT4_6_X = 389, // compare to "(evt.type=accept4 and evt.dir=<)" in a Falco rule
} ppm_event_code;
```
### Behavior Profiles fields
Compare to [Supported Fields for Conditions and Outputs](https://falco.org/docs/reference/rules/supported-fields/).
The list below is complete, and no other fields from Falco can be used for the behavior profiles at the moment. The binary will error out if used incorrectly. Thank you for your patience.
| Supported Behavior Profile Field | Description |
| --- | --- |
|proc.exe|The first command-line argument (i.e., argv[0]), typically the executable name or a custom string as specified by the user. It is primarily obtained from syscall arguments, truncated after 4096 bytes, or, as a fallback, by reading /proc/PID/cmdline, in which case it may be truncated after 1024 bytes. This field may differ from the last component of proc.exepath, reflecting how command invocation and execution paths can vary.|
|proc.pexe|The proc.exe (first command line argument argv[0]) of the parent process.|
|proc.aexe|The proc.exe (first command line argument argv[0]) for a specific process ancestor. You can access different levels of ancestors by using indices. For example, proc.aexe[1] retrieves the proc.exe of the parent process, proc.aexe[2] retrieves the proc.exe of the grandparent process, and so on. The current process's proc.exe line can be obtained using proc.aexe[0]. When used without any arguments, proc.aexe is applicable only in filters and matches any of the process ancestors. For instance, you can use `proc.aexe endswith java` to match any process ancestor whose proc.exe ends with the term `java`.|
|proc.exepath|The full executable path of a process, resolving to the canonical path for symlinks. This is primarily obtained from the kernel, or as a fallback, by reading /proc/PID/exe (in the latter case, the path is truncated after 1024 bytes). For eBPF drivers, due to verifier limits, path components may be truncated to 24 for legacy eBPF on kernel <5.2,48forlegacyeBPFonkernel>=5.2, or 96 for modern eBPF.|
|proc.pexepath|The proc.exepath (full executable path) of the parent process.|
|proc.aexepath|The proc.exepath (full executable path) for a specific process ancestor. You can access different levels of ancestors by using indices. For example, proc.aexepath[1] retrieves the proc.exepath of the parent process, proc.aexepath[2] retrieves the proc.exepath of the grandparent process, and so on. The current process's proc.exepath line can be obtained using proc.aexepath[0]. When used without any arguments, proc.aexepath is applicable only in filters and matches any of the process ancestors. For instance, you can use `proc.aexepath endswith java` to match any process ancestor whose path ends with the term `java`.|
|proc.name|The process name (truncated after 16 characters) generating the event (task->comm). Truncation is determined by kernel settings and not by Falco. This field is collected from the syscalls args or, as a fallback, extracted from /proc/PID/status. The name of the process and the name of the executable file on disk (if applicable) can be different if a process is given a custom name which is often the case for example for java applications.|
|proc.pname|The proc.name truncated after 16 characters) of the process generating the event.|
|proc.aname|The proc.name (truncated after 16 characters) for a specific process ancestor. You can access different levels of ancestors by using indices. For example, proc.aname[1] retrieves the proc.name of the parent process, proc.aname[2] retrieves the proc.name of the grandparent process, and so on. The current process's proc.name line can be obtained using proc.aname[0]. When used without any arguments, proc.aname is applicable only in filters and matches any of the process ancestors. For instance, you can use `proc.aname=bash` to match any process ancestor whose name is `bash`.|
|proc.args|The arguments passed on the command line when starting the process generating the event excluding argv[0] (truncated after 4096 bytes). This field is collected from the syscalls args or, as a fallback, extracted from /proc/PID/cmdline.|
|proc.cmdline|The concatenation of `proc.name + proc.args` (truncated after 4096 bytes) when starting the process generating the event.|
|proc.pcmdline|The proc.cmdline (full command line (proc.name + proc.args)) of the parent of the process generating the event.|
|proc.acmdline|The full command line (proc.name + proc.args) for a specific process ancestor. You can access different levels of ancestors by using indices. For example, proc.acmdline[1] retrieves the full command line of the parent process, proc.acmdline[2] retrieves the proc.cmdline of the grandparent process, and so on. The current process's full command line can be obtained using proc.acmdline[0]. When used without any arguments, proc.acmdline is applicable only in filters and matches any of the process ancestors. For instance, you can use `proc.acmdline contains base64` to match any process ancestor whose command line contains the term base64.|
|proc.cmdnargs|The number of command line args (proc.args).|
|proc.cmdlenargs|The total count of characters / length of the command line args (proc.args) combined excluding whitespaces between args.|
|proc.exeline|The full command line, with exe as first argument (proc.exe + proc.args) when starting the process generating the event.|
|proc.env|The environment variables of the process generating the event as concatenated string 'ENV_NAME=value ENV_NAME1=value1'. Can also be used to extract the value of a known env variable, e.g. proc.env[ENV_NAME].|
|proc.cwd|The current working directory of the event.|
|proc.tty|The controlling terminal of the process. 0 for processes without a terminal.|
|proc.pid|The id of the process generating the event.|
|proc.ppid|The pid of the parent of the process generating the event.|
|proc.apid|The pid for a specific process ancestor. You can access different levels of ancestors by using indices. For example, proc.apid[1] retrieves the pid of the parent process, proc.apid[2] retrieves the pid of the grandparent process, and so on. The current process's pid can be obtained using proc.apid[0]. When used without any arguments, proc.apid is applicable only in filters and matches any of the process ancestors. For instance, you can use `proc.apid=1337` to match any process ancestor whose pid is equal to 1337.|
|proc.vpid|The id of the process generating the event as seen from its current PID namespace.|
|proc.pvpid|The id of the parent process generating the event as seen from its current PID namespace.|
|proc.sid|The session id of the process generating the event.|
|proc.sname|The name of the current process's session leader. This is either the process with pid=proc.sid or the eldest ancestor that has the same sid as the current process.|
|proc.sid.exe|The first command line argument argv[0] (usually the executable name or a custom one) of the current process's session leader. This is either the process with pid=proc.sid or the eldest ancestor that has the same sid as the current process.|
|proc.sid.exepath|The full executable path of the current process's session leader. This is either the process with pid=proc.sid or the eldest ancestor that has the same sid as the current process.|
|proc.vpgid|The process group id of the process generating the event, as seen from its current PID namespace.|
|proc.vpgid.name|The name of the current process's process group leader. This is either the process with proc.vpgid == proc.vpid or the eldest ancestor that has the same vpgid as the current process. The description of `proc.is_vpgid_leader` offers additional insights.|
|proc.vpgid.exe|The first command line argument argv[0] (usually the executable name or a custom one) of the current process's process group leader. This is either the process with proc.vpgid == proc.vpid or the eldest ancestor that has the same vpgid as the current process. The description of `proc.is_vpgid_leader` offers additional insights.|
|proc.vpgid.exepath|The full executable path of the current process's process group leader. This is either the process with proc.vpgid == proc.vpid or the eldest ancestor that has the same vpgid as the current process. The description of `proc.is_vpgid_leader` offers additional insights.|
|proc.is_exe_writable|'true' if this process' executable file is writable by the same user that spawned the process.|
|proc.is_exe_upper_layer|'true' if this process' executable file is in upper layer in overlayfs. This field value can only be trusted if the underlying kernel version is greater or equal than 3.18.0, since overlayfs was introduced at that time.|
|proc.is_exe_from_memfd|'true' if the executable file of the current process is an anonymous file created using memfd_create() and is being executed by referencing its file descriptor (fd). This type of file exists only in memory and not on disk. Relevant to detect malicious in-memory code injection. Requires kernel version greater or equal to 3.17.0.|
|proc.is_sid_leader|'true' if this process is the leader of the process session, proc.sid == proc.vpid. For host processes vpid reflects pid.|
|proc.is_vpgid_leader|'true' if this process is the leader of the virtual process group, proc.vpgid == proc.vpid. For host processes vpgid and vpid reflect pgid and pid. Can help to distinguish if the process was 'directly' executed for instance in a tty (similar to bash history logging, `is_vpgid_leader` would be 'true') or executed as descendent process in the same process group which for example is the case when subprocesses are spawned from a script (`is_vpgid_leader` would be 'false').|
|proc.exe_ino|The inode number of the executable file on disk. Can be correlated with fd.ino.|
|proc.exe_ino.ctime|Last status change time of executable file (inode->ctime) as epoch timestamp in nanoseconds. Time is changed by writing or by setting inode information e.g. owner, group, link count, mode etc.|
|proc.exe_ino.mtime|Last modification time of executable file (inode->mtime) as epoch timestamp in nanoseconds. Time is changed by file modifications, e.g. by mknod, truncate, utime, write of more than zero bytes etc. For tracking changes in owner, group, link count or mode, use proc.exe_ino.ctime instead.|
|container.id|The truncated container ID (first 12 characters), e.g. 3ad7b26ded6d is extracted from the Linux cgroups by Falco within the kernel. Consequently, this field is reliably available and serves as the lookup key for Falco's synchronous or asynchronous requests against the container runtime socket to retrieve all other `'container.*'` information. One important aspect to be aware of is that if the process occurs on the host, meaning not in the container PID namespace, this field is set to a string called 'host'. In Kubernetes, pod sandbox container processes can exist where `container.id` matches `k8s.pod.sandbox_id`, lacking other 'container.*' details.|
|fd.num|the unique number identifying the file descriptor.|
|fd.name|FD full name. If the fd is a file, this field contains the full path. If the FD is a socket, this field contain the connection tuple.|
|fd.directory|If the fd is a file, the directory that contains it.|
|fd.filename|If the fd is a file, the filename without the path.|
|fd.dev|device number (major/minor) containing the referenced file|
|fd.ino|inode number of the referenced file|
|fd.nameraw|FD full name raw. Just like fd.name, but only used if fd is a file path. File path is kept raw with limited sanitization and without deriving the absolute path.|
|custom.proc.aname.lineage.join|[Incubating] String concatenate the process lineage to achieve better performance. It requires an argument to specify the maximum level of traversal, e.g. 'custom.proc.aname.lineage.join[7]'. This is a custom plugin specific field for the anomaly behavior profiles only. It may be dperecated in the future.|
|custom.proc.aexe.lineage.join|[Incubating] String concatenate the process lineage to achieve better performance. It requires an argument to specify the maximum level of traversal, e.g. 'custom.proc.aexe.lineage.join[7]'. This is a custom plugin specific field for the anomaly behavior profiles only. It may be dperecated in the future.|
|custom.proc.aexepath.lineage.join|[Incubating] String concatenate the process lineage to achieve better performance. It requires an argument to specify the maximum level of traversal, e.g. 'custom.proc.aexepath.lineage.join[7]'. This is a custom plugin specific field for the anomaly behavior profiles only. It may be dperecated in the future.|
|custom.fd.name.part1|[Incubating] For fd related network events only. Part 1 as string of the ip tuple in the format 'ip:port', e.g '172.40.111.222:54321' given fd.name '172.40.111.222:54321->142.251.111.147:443'. It may be dperecated in the future.|
|custom.fd.name.part2|[Incubating] For fd related network events only. Part 2 as string of the ip tuple in the format 'ip:port', e.g.'142.251.111.147:443' given fd.name '172.40.111.222:54321->142.251.111.147:443'. This is a custom plugin specific field for the anomaly behavior profiles only. It may be dperecated in the future.|
{PT_CHARBUF,EPF_ANOMALY_PLUGIN|EPF_NONE,PF_NA,"proc.exe","First Argument","The first command-line argument (i.e., argv[0]), typically the executable name or a custom string as specified by the user. It is primarily obtained from syscall arguments, truncated after 4096 bytes, or, as a fallback, by reading /proc/PID/cmdline, in which case it may be truncated after 1024 bytes. This field may differ from the last component of proc.exepath, reflecting how command invocation and execution paths can vary."},
{PT_CHARBUF,EPF_ANOMALY_PLUGIN|EPF_NONE,PF_NA,"proc.pexe","Parent First Argument","The proc.exe (first command line argument argv[0]) of the parent process."},
{PT_CHARBUF,EPF_ANOMALY_PLUGIN|EPF_ARG_ALLOWED|EPF_NO_RHS|EPF_NO_TRANSFORMER,PF_NA,"proc.aexe","Ancestor First Argument","The proc.exe (first command line argument argv[0]) for a specific process ancestor. You can access different levels of ancestors by using indices. For example, proc.aexe[1] retrieves the proc.exe of the parent process, proc.aexe[2] retrieves the proc.exe of the grandparent process, and so on. The current process's proc.exe line can be obtained using proc.aexe[0]. When used without any arguments, proc.aexe is applicable only in filters and matches any of the process ancestors. For instance, you can use `proc.aexe endswith java` to match any process ancestor whose proc.exe ends with the term `java`."},
{PT_CHARBUF,EPF_ANOMALY_PLUGIN|EPF_NONE,PF_NA,"proc.exepath","Process Executable Path","The full executable path of a process, resolving to the canonical path for symlinks. This is primarily obtained from the kernel, or as a fallback, by reading /proc/PID/exe (in the latter case, the path is truncated after 1024 bytes). For eBPF drivers, due to verifier limits, path components may be truncated to 24 for legacy eBPF on kernel <5.2, 48 for legacy eBPF on kernel >=5.2, or 96 for modern eBPF."},
{PT_CHARBUF,EPF_ANOMALY_PLUGIN|EPF_NONE,PF_NA,"proc.pexepath","Parent Process Executable Path","The proc.exepath (full executable path) of the parent process."},
{PT_CHARBUF,EPF_ANOMALY_PLUGIN|EPF_ARG_ALLOWED|EPF_NO_RHS|EPF_NO_TRANSFORMER,PF_NA,"proc.aexepath","Ancestor Executable Path","The proc.exepath (full executable path) for a specific process ancestor. You can access different levels of ancestors by using indices. For example, proc.aexepath[1] retrieves the proc.exepath of the parent process, proc.aexepath[2] retrieves the proc.exepath of the grandparent process, and so on. The current process's proc.exepath line can be obtained using proc.aexepath[0]. When used without any arguments, proc.aexepath is applicable only in filters and matches any of the process ancestors. For instance, you can use `proc.aexepath endswith java` to match any process ancestor whose path ends with the term `java`."},
{PT_CHARBUF,EPF_ANOMALY_PLUGIN|EPF_NONE,PF_NA,"proc.name","Name","The process name (truncated after 16 characters) generating the event (task->comm). Truncation is determined by kernel settings and not by Falco. This field is collected from the syscalls args or, as a fallback, extracted from /proc/PID/status. The name of the process and the name of the executable file on disk (if applicable) can be different if a process is given a custom name which is often the case for example for java applications."},
{PT_CHARBUF,EPF_ANOMALY_PLUGIN|EPF_NONE,PF_NA,"proc.pname","Parent Name","The proc.name truncated after 16 characters) of the process generating the event."},
{PT_CHARBUF,EPF_ANOMALY_PLUGIN|EPF_ARG_ALLOWED|EPF_NO_RHS|EPF_NO_TRANSFORMER,PF_NA,"proc.aname","Ancestor Name","The proc.name (truncated after 16 characters) for a specific process ancestor. You can access different levels of ancestors by using indices. For example, proc.aname[1] retrieves the proc.name of the parent process, proc.aname[2] retrieves the proc.name of the grandparent process, and so on. The current process's proc.name line can be obtained using proc.aname[0]. When used without any arguments, proc.aname is applicable only in filters and matches any of the process ancestors. For instance, you can use `proc.aname=bash` to match any process ancestor whose name is `bash`."},
{PT_CHARBUF,EPF_ANOMALY_PLUGIN|EPF_NONE,PF_NA,"proc.args","Arguments","The arguments passed on the command line when starting the process generating the event excluding argv[0] (truncated after 4096 bytes). This field is collected from the syscalls args or, as a fallback, extracted from /proc/PID/cmdline."},
{PT_CHARBUF,EPF_ANOMALY_PLUGIN|EPF_NONE,PF_NA,"proc.cmdline","Command Line","The concatenation of `proc.name + proc.args` (truncated after 4096 bytes) when starting the process generating the event."},
{PT_CHARBUF,EPF_ANOMALY_PLUGIN|EPF_NONE,PF_NA,"proc.pcmdline","Parent Command Line","The proc.cmdline (full command line (proc.name + proc.args)) of the parent of the process generating the event."},
{PT_CHARBUF,EPF_ANOMALY_PLUGIN|EPF_ARG_ALLOWED|EPF_NO_RHS|EPF_NO_TRANSFORMER,PF_NA,"proc.acmdline","Ancestor Command Line","The full command line (proc.name + proc.args) for a specific process ancestor. You can access different levels of ancestors by using indices. For example, proc.acmdline[1] retrieves the full command line of the parent process, proc.acmdline[2] retrieves the proc.cmdline of the grandparent process, and so on. The current process's full command line can be obtained using proc.acmdline[0]. When used without any arguments, proc.acmdline is applicable only in filters and matches any of the process ancestors. For instance, you can use `proc.acmdline contains base64` to match any process ancestor whose command line contains the term base64."},
{PT_UINT64,EPF_ANOMALY_PLUGIN|EPF_NONE,PF_DEC,"proc.cmdnargs","Number of Command Line args","The number of command line args (proc.args)."},
{PT_UINT64,EPF_ANOMALY_PLUGIN|EPF_NONE,PF_DEC,"proc.cmdlenargs","Total Count of Characters in Command Line args","The total count of characters / length of the command line args (proc.args) combined excluding whitespaces between args."},
{PT_CHARBUF,EPF_ANOMALY_PLUGIN|EPF_NONE,PF_NA,"proc.exeline","Executable Command Line","The full command line, with exe as first argument (proc.exe + proc.args) when starting the process generating the event."},
{PT_CHARBUF,EPF_ANOMALY_PLUGIN|EPF_ARG_ALLOWED,PF_NA,"proc.env","Environment","The environment variables of the process generating the event as concatenated string 'ENV_NAME=value ENV_NAME1=value1'. Can also be used to extract the value of a known env variable, e.g. proc.env[ENV_NAME]."},
{PT_CHARBUF,EPF_ARG_ALLOWED|EPF_NO_RHS|EPF_NO_TRANSFORMER,PF_NA,"proc.aenv","Ancestor Environment","[EXPERIMENTAL] This field can be used in three flavors: (1) as a filter checking all parents, e.g. 'proc.aenv contains xyz', which is similar to the familiar 'proc.aname contains xyz' approach, (2) checking the `proc.env` of a specified level of the parent, e.g. 'proc.aenv[2]', which is similar to the familiar 'proc.aname[2]' approach, or (3) checking the first matched value of a known ENV_NAME in the parent lineage, such as 'proc.aenv[ENV_NAME]' (across a max of 20 ancestor levels). This field may be deprecated or undergo breaking changes in future releases. Please use it with caution."},
{PT_CHARBUF,EPF_ANOMALY_PLUGIN|EPF_NONE,PF_NA,"proc.cwd","Current Working Directory","The current working directory of the event."},
{PT_INT64,EPF_NONE,PF_ID,"proc.loginshellid","Login Shell ID","The pid of the oldest shell among the ancestors of the current process, if there is one. This field can be used to separate different user sessions."},
{PT_UINT32,EPF_ANOMALY_PLUGIN|EPF_NONE,PF_ID,"proc.tty","Process TTY","The controlling terminal of the process. 0 for processes without a terminal."},
{PT_INT64,EPF_ANOMALY_PLUGIN|EPF_NONE,PF_ID,"proc.pid","Process ID","The id of the process generating the event."},
{PT_INT64,EPF_ANOMALY_PLUGIN|EPF_NONE,PF_ID,"proc.ppid","Parent Process ID","The pid of the parent of the process generating the event."},
{PT_INT64,EPF_ANOMALY_PLUGIN|EPF_ARG_ALLOWED|EPF_NO_RHS|EPF_NO_TRANSFORMER,PF_ID,"proc.apid","Ancestor Process ID","The pid for a specific process ancestor. You can access different levels of ancestors by using indices. For example, proc.apid[1] retrieves the pid of the parent process, proc.apid[2] retrieves the pid of the grandparent process, and so on. The current process's pid can be obtained using proc.apid[0]. When used without any arguments, proc.apid is applicable only in filters and matches any of the process ancestors. For instance, you can use `proc.apid=1337` to match any process ancestor whose pid is equal to 1337."},
{PT_INT64,EPF_ANOMALY_PLUGIN|EPF_NONE,PF_ID,"proc.vpid","Virtual Process ID","The id of the process generating the event as seen from its current PID namespace."},
{PT_INT64,EPF_ANOMALY_PLUGIN|EPF_NONE,PF_ID,"proc.pvpid","Parent Virtual Process ID","The id of the parent process generating the event as seen from its current PID namespace."},
{PT_INT64,EPF_ANOMALY_PLUGIN|EPF_NONE,PF_ID,"proc.sid","Process Session ID","The session id of the process generating the event."},
{PT_CHARBUF,EPF_ANOMALY_PLUGIN|EPF_NONE,PF_NA,"proc.sname","Process Session Name","The name of the current process's session leader. This is either the process with pid=proc.sid or the eldest ancestor that has the same sid as the current process."},
{PT_CHARBUF,EPF_ANOMALY_PLUGIN|EPF_NONE,PF_NA,"proc.sid.exe","Process Session First Argument","The first command line argument argv[0] (usually the executable name or a custom one) of the current process's session leader. This is either the process with pid=proc.sid or the eldest ancestor that has the same sid as the current process."},
{PT_CHARBUF,EPF_ANOMALY_PLUGIN|EPF_NONE,PF_NA,"proc.sid.exepath","Process Session Executable Path","The full executable path of the current process's session leader. This is either the process with pid=proc.sid or the eldest ancestor that has the same sid as the current process."},
{PT_INT64,EPF_ANOMALY_PLUGIN|EPF_NONE,PF_ID,"proc.vpgid","Process Virtual Group ID","The process group id of the process generating the event, as seen from its current PID namespace."},
{PT_CHARBUF,EPF_ANOMALY_PLUGIN|EPF_NONE,PF_NA,"proc.vpgid.name","Process Group Name","The name of the current process's process group leader. This is either the process with proc.vpgid == proc.vpid or the eldest ancestor that has the same vpgid as the current process. The description of `proc.is_vpgid_leader` offers additional insights."},
{PT_CHARBUF,EPF_ANOMALY_PLUGIN|EPF_NONE,PF_NA,"proc.vpgid.exe","Process Group First Argument","The first command line argument argv[0] (usually the executable name or a custom one) of the current process's process group leader. This is either the process with proc.vpgid == proc.vpid or the eldest ancestor that has the same vpgid as the current process. The description of `proc.is_vpgid_leader` offers additional insights."},
{PT_CHARBUF,EPF_ANOMALY_PLUGIN|EPF_NONE,PF_NA,"proc.vpgid.exepath","Process Group Executable Path","The full executable path of the current process's process group leader. This is either the process with proc.vpgid == proc.vpid or the eldest ancestor that has the same vpgid as the current process. The description of `proc.is_vpgid_leader` offers additional insights."},
{PT_RELTIME,EPF_NONE,PF_DEC,"proc.duration","Process Duration","Number of nanoseconds since the process started."},
{PT_RELTIME,EPF_NONE,PF_DEC,"proc.ppid.duration","Parent Process Duration","Number of nanoseconds since the parent process started."},
{PT_RELTIME,EPF_NONE,PF_DEC,"proc.pid.ts","Process start ts","Start of process as epoch timestamp in nanoseconds."},
{PT_RELTIME,EPF_NONE,PF_DEC,"proc.ppid.ts","Parent Process start ts","Start of parent process as epoch timestamp in nanoseconds."},
{PT_BOOL,EPF_ANOMALY_PLUGIN|EPF_NONE,PF_NA,"proc.is_exe_writable","Process Executable Is Writable","'true' if this process' executable file is writable by the same user that spawned the process."},
{PT_BOOL,EPF_ANOMALY_PLUGIN|EPF_NONE,PF_NA,"proc.is_exe_upper_layer","Process Executable Is In Upper Layer","'true' if this process' executable file is in upper layer in overlayfs. This field value can only be trusted if the underlying kernel version is greater or equal than 3.18.0, since overlayfs was introduced at that time."},
{PT_BOOL,EPF_ANOMALY_PLUGIN|EPF_NONE,PF_NA,"proc.is_exe_from_memfd","Process Executable Is Stored In Memfd","'true' if the executable file of the current process is an anonymous file created using memfd_create() and is being executed by referencing its file descriptor (fd). This type of file exists only in memory and not on disk. Relevant to detect malicious in-memory code injection. Requires kernel version greater or equal to 3.17.0."},
{PT_BOOL,EPF_ANOMALY_PLUGIN|EPF_NONE,PF_NA,"proc.is_sid_leader","Process Is Process Session Leader","'true' if this process is the leader of the process session, proc.sid == proc.vpid. For host processes vpid reflects pid."},
{PT_BOOL,EPF_ANOMALY_PLUGIN|EPF_NONE,PF_NA,"proc.is_vpgid_leader","Process Is Virtual Process Group Leader","'true' if this process is the leader of the virtual process group, proc.vpgid == proc.vpid. For host processes vpgid and vpid reflect pgid and pid. Can help to distinguish if the process was 'directly' executed for instance in a tty (similar to bash history logging, `is_vpgid_leader` would be 'true') or executed as descendent process in the same process group which for example is the case when subprocesses are spawned from a script (`is_vpgid_leader` would be 'false')."},
{PT_INT64,EPF_ANOMALY_PLUGIN|EPF_NONE,PF_DEC,"proc.exe_ino","Inode number of executable file on disk","The inode number of the executable file on disk. Can be correlated with fd.ino."},
{PT_ABSTIME,EPF_ANOMALY_PLUGIN|EPF_NONE,PF_DEC,"proc.exe_ino.ctime","Last status change time (ctime) of executable file","Last status change time of executable file (inode->ctime) as epoch timestamp in nanoseconds. Time is changed by writing or by setting inode information e.g. owner, group, link count, mode etc."},
{PT_ABSTIME,EPF_ANOMALY_PLUGIN|EPF_NONE,PF_DEC,"proc.exe_ino.mtime","Last modification time (mtime) of executable file","Last modification time of executable file (inode->mtime) as epoch timestamp in nanoseconds. Time is changed by file modifications, e.g. by mknod, truncate, utime, write of more than zero bytes etc. For tracking changes in owner, group, link count or mode, use proc.exe_ino.ctime instead."},
{PT_ABSTIME,EPF_NONE,PF_DEC,"proc.exe_ino.ctime_duration_proc_start","Number of nanoseconds between ctime exe file and proc clone ts","Number of nanoseconds between modifying status of executable image and spawning a new process using the changed executable image."},
{PT_ABSTIME,EPF_NONE,PF_DEC,"proc.exe_ino.ctime_duration_pidns_start","Number of nanoseconds between pidns start ts and ctime exe file","Number of nanoseconds between PID namespace start ts and ctime exe file if PID namespace start predates ctime."},
{PT_UINT64,EPF_NONE,PF_DEC,"proc.pidns_init_start_ts","Start ts of pid namespace","Start of PID namespace (container or non container pid namespace) as epoch timestamp in nanoseconds."},
{PT_BOOL,EPF_NONE,PF_NA,"proc.is_container_healthcheck","Process Is Container Healthcheck","'true' if this process is running as a part of the container's health check."},
{PT_BOOL,EPF_NONE,PF_NA,"proc.is_container_liveness_probe","Process Is Container Liveness","'true' if this process is running as a part of the container's liveness probe."},
{PT_BOOL,EPF_NONE,PF_NA,"proc.is_container_readiness_probe","Process Is Container Readiness","'true' if this process is running as a part of the container's readiness probe."},
{PT_UINT64,EPF_NONE,PF_DEC,"proc.fdopencount","FD Count","Number of open FDs for the process"},
{PT_INT64,EPF_NONE,PF_DEC,"proc.fdlimit","FD Limit","Maximum number of FDs the process can open."},
{PT_DOUBLE,EPF_NONE,PF_NA,"proc.fdusage","FD Usage","The ratio between open FDs and maximum available FDs for the process."},
{PT_UINT64,EPF_NONE,PF_DEC,"proc.vmsize","VM Size","Total virtual memory for the process (as kb)."},
{PT_UINT64,EPF_NONE,PF_DEC,"proc.vmrss","VM RSS","Resident non-swapped memory for the process (as kb)."},
{PT_UINT64,EPF_NONE,PF_DEC,"proc.vmswap","VM Swap","Swapped memory for the process (as kb)."},
{PT_UINT64,EPF_NONE,PF_DEC,"thread.pfmajor","Major Page Faults","Number of major page faults since thread start."},
{PT_UINT64,EPF_NONE,PF_DEC,"thread.pfminor","Minor Page Faults","Number of minor page faults since thread start."},
{PT_INT64,EPF_NONE,PF_ID,"thread.tid","Thread ID","The id of the thread generating the event."},
{PT_BOOL,EPF_NONE,PF_NA,"thread.ismain","Main Thread","'true' if the thread generating the event is the main one in the process."},
{PT_INT64,EPF_NONE,PF_ID,"thread.vtid","Virtual Thread ID","The id of the thread generating the event as seen from its current PID namespace."},
{PT_CHARBUF,EPF_TABLE_ONLY,PF_NA,"thread.nametid","Thread Name + ID","This field chains the process name and tid of a thread and can be used as a specific identifier of a thread for a specific execve."},
{PT_RELTIME,EPF_NONE,PF_DEC,"thread.exectime","Scheduled Thread CPU Time","CPU time spent by the last scheduled thread, in nanoseconds. Exported by switch events only."},
{PT_RELTIME,EPF_NONE,PF_DEC,"thread.totexectime","Current Thread CPU Time","Total CPU time, in nanoseconds since the beginning of the capture, for the current thread. Exported by switch events only."},
{PT_CHARBUF,EPF_NONE,PF_NA,"thread.cgroups","Thread Cgroups","All cgroups the thread belongs to, aggregated into a single string."},
{PT_CHARBUF,EPF_ARG_REQUIRED,PF_NA,"thread.cgroup","Thread Cgroup","The cgroup the thread belongs to, for a specific subsystem. e.g. thread.cgroup.cpuacct."},
{PT_UINT64,EPF_NONE,PF_DEC,"proc.nthreads","Threads","The number of alive threads that the process generating the event currently has, including the leader thread. Please note that the leader thread may not be here, in that case 'proc.nthreads' and 'proc.nchilds' are equal"},
{PT_UINT64,EPF_NONE,PF_DEC,"proc.nchilds","Children","The number of alive not leader threads that the process generating the event currently has. This excludes the leader thread."},
{PT_DOUBLE,EPF_NONE,PF_NA,"thread.cpu","Thread CPU","The CPU consumed by the thread in the last second."},
{PT_DOUBLE,EPF_NONE,PF_NA,"thread.cpu.user","Thread User CPU","The user CPU consumed by the thread in the last second."},
{PT_DOUBLE,EPF_NONE,PF_NA,"thread.cpu.system","Thread System CPU","The system CPU consumed by the thread in the last second."},
{PT_UINT64,EPF_NONE,PF_DEC,"thread.vmsize","Thread VM Size (kb)","For the process main thread, this is the total virtual memory for the process (as kb). For the other threads, this field is zero."},
{PT_UINT64,EPF_NONE,PF_DEC,"thread.vmrss","Thread VM RSS (kb)","For the process main thread, this is the resident non-swapped memory for the process (as kb). For the other threads, this field is zero."},
{PT_UINT64,EPF_TABLE_ONLY,PF_DEC,"thread.vmsize.b","Thread VM Size (b)","For the process main thread, this is the total virtual memory for the process (in bytes). For the other threads, this field is zero."},
{PT_UINT64,EPF_TABLE_ONLY,PF_DEC,"thread.vmrss.b","Thread VM RSS (b)","For the process main thread, this is the resident non-swapped memory for the process (in bytes). For the other threads, this field is zero."},
{PT_CHARBUF,EPF_ANOMALY_PLUGIN|EPF_NONE,PF_NA,"container.id","Container ID","The truncated container ID (first 12 characters), e.g. 3ad7b26ded6d is extracted from the Linux cgroups by Falco within the kernel. Consequently, this field is reliably available and serves as the lookup key for Falco's synchronous or asynchronous requests against the container runtime socket to retrieve all other 'container.*' information. One important aspect to be aware of is that if the process occurs on the host, meaning not in the container PID namespace, this field is set to a string called 'host'. In Kubernetes, pod sandbox container processes can exist where `container.id` matches `k8s.pod.sandbox_id`, lacking other 'container.*' details."},
{PT_CHARBUF,EPF_NONE,PF_NA,"container.full_id","Container ID","The full container ID, e.g. 3ad7b26ded6d8e7b23da7d48fe889434573036c27ae5a74837233de441c3601e. In contrast to `container.id`, we enrich this field as part of the container engine enrichment. In instances of userspace container engine lookup delays, this field may not be available yet."},
{PT_CHARBUF,EPF_NONE,PF_NA,"container.name","Container Name","The container name. In instances of userspace container engine lookup delays, this field may not be available yet. One important aspect to be aware of is that if the process occurs on the host, meaning not in the container PID namespace, this field is set to a string called 'host'."},
{PT_CHARBUF,EPF_NONE,PF_NA,"container.image","Image Name","The container image name (e.g. falcosecurity/falco:latest for docker). In instances of userspace container engine lookup delays, this field may not be available yet."},
{PT_CHARBUF,EPF_NONE,PF_NA,"container.image.id","Image ID","The container image id (e.g. 6f7e2741b66b). In instances of userspace container engine lookup delays, this field may not be available yet."},
{PT_CHARBUF,EPF_NONE,PF_NA,"container.type","Type","The container type, e.g. docker, cri-o, containerd etc."},
{PT_BOOL,EPF_NONE,PF_NA,"container.privileged","Privileged","'true' for containers running as privileged, 'false' otherwise. In instances of userspace container engine lookup delays, this field may not be available yet."},
{PT_CHARBUF,EPF_NONE,PF_NA,"container.mounts","Mounts","A space-separated list of mount information. Each item in the list has the format 'source:dest:mode:rdrw:propagation'. In instances of userspace container engine lookup delays, this field may not be available yet."},
{PT_CHARBUF,EPF_ARG_REQUIRED,PF_NA,"container.mount","Mount","Information about a single mount, specified by number (e.g. container.mount[0]) or mount source (container.mount[/usr/local]). The pathname can be a glob (container.mount[/usr/local/*]), in which case the first matching mount will be returned. The information has the format 'source:dest:mode:rdrw:propagation'. If there is no mount with the specified index or matching the provided source, returns the string \"none\" instead of a NULL value. In instances of userspace container engine lookup delays, this field may not be available yet."},
{PT_CHARBUF,EPF_ARG_REQUIRED,PF_NA,"container.mount.source","Mount Source","The mount source, specified by number (e.g. container.mount.source[0]) or mount destination (container.mount.source[/host/lib/modules]). The pathname can be a glob. In instances of userspace container engine lookup delays, this field may not be available yet."},
{PT_CHARBUF,EPF_ARG_REQUIRED,PF_NA,"container.mount.dest","Mount Destination","The mount destination, specified by number (e.g. container.mount.dest[0]) or mount source (container.mount.dest[/lib/modules]). The pathname can be a glob. In instances of userspace container engine lookup delays, this field may not be available yet."},
{PT_CHARBUF,EPF_ARG_REQUIRED,PF_NA,"container.mount.mode","Mount Mode","The mount mode, specified by number (e.g. container.mount.mode[0]) or mount source (container.mount.mode[/usr/local]). The pathname can be a glob. In instances of userspace container engine lookup delays, this field may not be available yet."},
{PT_CHARBUF,EPF_ARG_REQUIRED,PF_NA,"container.mount.rdwr","Mount Read/Write","The mount rdwr value, specified by number (e.g. container.mount.rdwr[0]) or mount source (container.mount.rdwr[/usr/local]). The pathname can be a glob. In instances of userspace container engine lookup delays, this field may not be available yet."},
{PT_CHARBUF,EPF_ARG_REQUIRED,PF_NA,"container.mount.propagation","Mount Propagation","The mount propagation value, specified by number (e.g. container.mount.propagation[0]) or mount source (container.mount.propagation[/usr/local]). The pathname can be a glob. In instances of userspace container engine lookup delays, this field may not be available yet."},
{PT_CHARBUF,EPF_NONE,PF_NA,"container.image.repository","Repository","The container image repository (e.g. falcosecurity/falco). In instances of userspace container engine lookup delays, this field may not be available yet."},
{PT_CHARBUF,EPF_NONE,PF_NA,"container.image.tag","Image Tag","The container image tag (e.g. stable, latest). In instances of userspace container engine lookup delays, this field may not be available yet."},
{PT_CHARBUF,EPF_NONE,PF_NA,"container.image.digest","Registry Digest","The container image registry digest (e.g. sha256:d977378f890d445c15e51795296e4e5062f109ce6da83e0a355fc4ad8699d27). In instances of userspace container engine lookup delays, this field may not be available yet."},
{PT_CHARBUF,EPF_NONE,PF_NA,"container.healthcheck","Health Check","The container's health check. Will be the null value (\"N/A\") if no healthcheck configured, \"NONE\" if configured but explicitly not created, and the healthcheck command line otherwise. In instances of userspace container engine lookup delays, this field may not be available yet."},
{PT_CHARBUF,EPF_NONE,PF_NA,"container.liveness_probe","Liveness","The container's liveness probe. Will be the null value (\"N/A\") if no liveness probe configured, the liveness probe command line otherwise. In instances of userspace container engine lookup delays, this field may not be available yet."},
{PT_CHARBUF,EPF_NONE,PF_NA,"container.readiness_probe","Readiness","The container's readiness probe. Will be the null value (\"N/A\") if no readiness probe configured, the readiness probe command line otherwise. In instances of userspace container engine lookup delays, this field may not be available yet."},
{PT_UINT64,EPF_NONE,PF_DEC,"container.start_ts","Container start","Container start as epoch timestamp in nanoseconds based on proc.pidns_init_start_ts and extracted in the kernel and not from the container runtime socket / container engine."},
{PT_RELTIME,EPF_NONE,PF_DEC,"container.duration","Number of nanoseconds since container.start_ts","Number of nanoseconds since container.start_ts."},
{PT_CHARBUF,EPF_NONE,PF_NA,"container.ip","Container ip address","The container's / pod's primary ip address as retrieved from the container engine. Only ipv4 addresses are tracked. Consider container.cni.json (CRI use case) for logging ip addresses for each network interface. In instances of userspace container engine lookup delays, this field may not be available yet."},
{PT_CHARBUF,EPF_NONE,PF_NA,"container.cni.json","Container's / pod's CNI result json","The container's / pod's CNI result field from the respective pod status info. It contains ip addresses for each network interface exposed as unparsed escaped JSON string. Supported for CRI container engine (containerd, cri-o runtimes), optimized for containerd (some non-critical JSON keys removed). Useful for tracking ips (ipv4 and ipv6, dual-stack support) for each network interface (multi-interface support). In instances of userspace container engine lookup delays, this field may not be available yet."},
{PT_INT64,EPF_ANOMALY_PLUGIN|EPF_NONE,PF_ID,"fd.num","FD Number","the unique number identifying the file descriptor."},
{PT_CHARBUF,EPF_NONE,PF_DEC,"fd.type","FD Type","type of FD. Can be 'file', 'directory', 'ipv4', 'ipv6', 'unix', 'pipe', 'event', 'signalfd', 'eventpoll', 'inotify' 'signalfd' or 'memfd'."},
{PT_CHARBUF,EPF_NONE,PF_DEC,"fd.typechar","FD Type Char","type of FD as a single character. Can be 'f' for file, 4 for IPv4 socket, 6 for IPv6 socket, 'u' for unix socket, p for pipe, 'e' for eventfd, 's' for signalfd, 'l' for eventpoll, 'i' for inotify, 'b' for bpf, 'u' for userfaultd, 'r' for io_uring, 'm' for memfd ,'o' for unknown."},
{PT_CHARBUF,EPF_ANOMALY_PLUGIN|EPF_NONE,PF_NA,"fd.name","FD Name","FD full name. If the fd is a file, this field contains the full path. If the FD is a socket, this field contain the connection tuple."},
{PT_CHARBUF,EPF_ANOMALY_PLUGIN|EPF_NONE,PF_NA,"fd.directory","FD Directory","If the fd is a file, the directory that contains it."},
{PT_CHARBUF,EPF_ANOMALY_PLUGIN|EPF_NONE,PF_NA,"fd.filename","FD Filename","If the fd is a file, the filename without the path."},
{PT_IPADDR,EPF_FILTER_ONLY|EPF_NO_RHS|EPF_NO_TRANSFORMER,PF_NA,"fd.ip","FD IP Address","matches the ip address (client or server) of the fd."},
{PT_IPADDR,EPF_NONE,PF_NA,"fd.cip","FD Client Address","client IP address."},
{PT_IPADDR,EPF_NONE,PF_NA,"fd.sip","FD Server Address","server IP address."},
{PT_IPADDR,EPF_NONE,PF_NA,"fd.lip","FD Local Address","local IP address."},
{PT_IPADDR,EPF_NONE,PF_NA,"fd.rip","FD Remote Address","remote IP address."},
{PT_PORT,EPF_FILTER_ONLY|EPF_NO_RHS|EPF_NO_TRANSFORMER,PF_DEC,"fd.port","FD Port","matches the port (either client or server) of the fd."},
{PT_PORT,EPF_NONE,PF_DEC,"fd.cport","FD Client Port","for TCP/UDP FDs, the client port."},
{PT_PORT,EPF_NONE,PF_DEC,"fd.sport","FD Server Port","for TCP/UDP FDs, server port."},
{PT_PORT,EPF_NONE,PF_DEC,"fd.lport","FD Local Port","for TCP/UDP FDs, the local port."},
{PT_PORT,EPF_NONE,PF_DEC,"fd.rport","FD Remote Port","for TCP/UDP FDs, the remote port."},
{PT_CHARBUF,EPF_NONE,PF_NA,"fd.l4proto","FD IP Protocol","the IP protocol of a socket. Can be 'tcp', 'udp', 'icmp' or 'raw'."},
{PT_CHARBUF,EPF_NONE,PF_NA,"fd.sockfamily","FD Socket Family","the socket family for socket events. Can be 'ip' or 'unix'."},
{PT_BOOL,EPF_NONE,PF_NA,"fd.is_server","FD Server","'true' if the process owning this FD is the server endpoint in the connection."},
{PT_CHARBUF,EPF_NONE,PF_NA,"fd.uid","FD ID","a unique identifier for the FD, created by chaining the FD number and the thread ID."},
{PT_CHARBUF,EPF_NONE,PF_NA,"fd.containername","FD Container Name","chaining of the container ID and the FD name. Useful when trying to identify which container an FD belongs to."},
{PT_CHARBUF,EPF_NONE,PF_NA,"fd.containerdirectory","FD Container Directory","chaining of the container ID and the directory name. Useful when trying to identify which container a directory belongs to."},
{PT_PORT,EPF_FILTER_ONLY|EPF_NO_RHS|EPF_NO_TRANSFORMER,PF_NA,"fd.proto","FD Protocol","matches the protocol (either client or server) of the fd."},
{PT_CHARBUF,EPF_NONE,PF_NA,"fd.cproto","FD Client Protocol","for TCP/UDP FDs, the client protocol."},
{PT_CHARBUF,EPF_NONE,PF_NA,"fd.sproto","FD Server Protocol","for TCP/UDP FDs, server protocol."},
{PT_CHARBUF,EPF_NONE,PF_NA,"fd.lproto","FD Local Protocol","for TCP/UDP FDs, the local protocol."},
{PT_CHARBUF,EPF_NONE,PF_NA,"fd.rproto","FD Remote Protocol","for TCP/UDP FDs, the remote protocol."},
{PT_IPNET,EPF_FILTER_ONLY|EPF_NO_RHS|EPF_NO_TRANSFORMER,PF_NA,"fd.net","FD IP Network","matches the IP network (client or server) of the fd."},
{PT_IPNET,EPF_FILTER_ONLY|EPF_NO_RHS|EPF_NO_TRANSFORMER,PF_NA,"fd.cnet","FD Client Network","matches the client IP network of the fd."},
{PT_IPNET,EPF_FILTER_ONLY|EPF_NO_RHS|EPF_NO_TRANSFORMER,PF_NA,"fd.snet","FD Server Network","matches the server IP network of the fd."},
{PT_IPNET,EPF_FILTER_ONLY|EPF_NO_RHS|EPF_NO_TRANSFORMER,PF_NA,"fd.lnet","FD Local Network","matches the local IP network of the fd."},
{PT_IPNET,EPF_FILTER_ONLY|EPF_NO_RHS|EPF_NO_TRANSFORMER,PF_NA,"fd.rnet","FD Remote Network","matches the remote IP network of the fd."},
{PT_BOOL,EPF_NONE,PF_NA,"fd.connected","FD Connected","for TCP/UDP FDs, 'true' if the socket is connected."},
{PT_BOOL,EPF_NONE,PF_NA,"fd.name_changed","FD Name Changed","True when an event changes the name of an fd used by this event. This can occur in some cases such as udp connections where the connection tuple changes."},
{PT_CHARBUF,EPF_NO_RHS|EPF_NO_TRANSFORMER,PF_NA,"fd.cip.name","FD Client Domain Name","Domain name associated with the client IP address."},
{PT_CHARBUF,EPF_NO_RHS|EPF_NO_TRANSFORMER,PF_NA,"fd.sip.name","FD Server Domain Name","Domain name associated with the server IP address."},
{PT_CHARBUF,EPF_NO_RHS|EPF_NO_TRANSFORMER,PF_NA,"fd.lip.name","FD Local Domain Name","Domain name associated with the local IP address."},
{PT_CHARBUF,EPF_NO_RHS|EPF_NO_TRANSFORMER,PF_NA,"fd.rip.name","FD Remote Domain Name","Domain name associated with the remote IP address."},
{PT_INT32,EPF_ANOMALY_PLUGIN|EPF_NONE,PF_HEX,"fd.dev","FD Device","device number (major/minor) containing the referenced file"},
{PT_INT32,EPF_NONE,PF_DEC,"fd.dev.major","FD Major Device","major device number containing the referenced file"},
{PT_INT32,EPF_NONE,PF_DEC,"fd.dev.minor","FD Minor Device","minor device number containing the referenced file"},
{PT_INT64,EPF_ANOMALY_PLUGIN|EPF_NONE,PF_DEC,"fd.ino","FD Inode Number","inode number of the referenced file"},
{PT_CHARBUF,EPF_ANOMALY_PLUGIN|EPF_NONE,PF_NA,"fd.nameraw","FD Name Raw","FD full name raw. Just like fd.name, but only used if fd is a file path. File path is kept raw with limited sanitization and without deriving the absolute path."},
{PT_CHARBUF,EPF_IS_LIST|EPF_ARG_ALLOWED|EPF_NO_RHS|EPF_NO_TRANSFORMER,PF_DEC,"fd.types","FD Type","List of FD types in used. Can be passed an fd number e.g. fd.types[0] to get the type of stdout as a single item list."},
{PT_CHARBUF,EPF_NONE,PF_NA,"fs.path.name","Path for Filesystem-related operation","For any event type that deals with a filesystem path, the path the file syscall is operating on. This path is always fully resolved, prepending the thread cwd when needed."},
{PT_CHARBUF,EPF_NONE,PF_NA,"fs.path.nameraw","Raw path for Filesystem-related operation","For any event type that deals with a filesystem path, the path the file syscall is operating on. This path is always the path provided to the syscall and may not be fully resolved."},
{PT_CHARBUF,EPF_NONE,PF_NA,"fs.path.source","Source path for Filesystem-related operation","For any event type that deals with a filesystem path, and specifically for a source and target like mv, cp, etc, the source path the file syscall is operating on. This path is always fully resolved, prepending the thread cwd when needed."},
{PT_CHARBUF,EPF_NONE,PF_NA,"fs.path.sourceraw","Source path for Filesystem-related operation","For any event type that deals with a filesystem path, and specifically for a source and target like mv, cp, etc, the source path the file syscall is operating on. This path is always the path provided to the syscall and may not be fully resolved."},
{PT_CHARBUF,EPF_NONE,PF_NA,"fs.path.target","Target path for Filesystem-related operation","For any event type that deals with a filesystem path, and specifically for a target and target like mv, cp, etc, the target path the file syscall is operating on. This path is always fully resolved, prepending the thread cwd when needed."},
{PT_CHARBUF,EPF_NONE,PF_NA,"fs.path.targetraw","Target path for Filesystem-related operation","For any event type that deals with a filesystem path, and specifically for a target and target like mv, cp, etc, the target path the file syscall is operating on. This path is always the path provided to the syscall and may not be fully resolved."},
{PT_CHARBUF,EPF_ANOMALY_PLUGIN|EPF_ARG_REQUIRED,PF_NA,"custom.proc.aname.lineage.join","Custom concat lineage","[Incubating] String concatenate the process lineage to achieve better performance. It requires an argument to specify the maximum level of traversal, e.g. 'custom.proc.aname.lineage.join[7]'. This is a custom plugin specific field for the anomaly behavior profiles only. It may be dperecated in the future."},
{PT_CHARBUF,EPF_ANOMALY_PLUGIN|EPF_ARG_REQUIRED,PF_NA,"custom.proc.aexe.lineage.join","Custom concat lineage","[Incubating] String concatenate the process lineage to achieve better performance. It requires an argument to specify the maximum level of traversal, e.g. 'custom.proc.aexe.lineage.join[7]'. This is a custom plugin specific field for the anomaly behavior profiles only. It may be dperecated in the future."},
{PT_CHARBUF,EPF_ANOMALY_PLUGIN|EPF_ARG_REQUIRED,PF_NA,"custom.proc.aexepath.lineage.join","Custom concat lineage","[Incubating] String concatenate the process lineage to achieve better performance. It requires an argument to specify the maximum level of traversal, e.g. 'custom.proc.aexepath.lineage.join[7]'. This is a custom plugin specific field for the anomaly behavior profiles only. It may be dperecated in the future."},
{PT_CHARBUF,EPF_ANOMALY_PLUGIN|EPF_NONE,PF_NA,"custom.fd.name.part1","Custom fd 'ip:port' part1","[Incubating] For fd related network events only. Part 1 as string of the ip tuple in the format 'ip:port', e.g '172.40.111.222:54321' given fd.name '172.40.111.222:54321->142.251.111.147:443'. It may be dperecated in the future."},
{PT_CHARBUF,EPF_ANOMALY_PLUGIN|EPF_NONE,PF_NA,"custom.fd.name.part2","Custom fd 'ip:port' part1","[Incubating] For fd related network events only. Part 2 as string of the ip tuple in the format 'ip:port', e.g.'142.251.111.147:443' given fd.name '172.40.111.222:54321->142.251.111.147:443'. This is a custom plugin specific field for the anomaly behavior profiles only. It may be dperecated in the future."},
};
namespaceplugin_anomalydetection::utils
{
// Adopted from falcosecurity/libs, custom hand-rolled for performance reasons
plugin_anomalydetection::utils::log_error("Usage of behavior profile field: '"+fieldname+"' requires an argument greater than 0 indicating the level of parent lineage traversal, e.g. '%custom.proc.aname.lineage.join[7]' or '%custom.proc.aexe.lineage.join[7]' or '%custom.proc.aexepath.lineage.join[7]' exiting...");
# Tests Leveraging `libsinsp` Unit Tests Framework
We leverage the [falcosecurity/libs](https://github.com/falcosecurity/libs) `libsinsp` unit test framework for the `anomalydetection` plugin tests. This way, we can check the compatibility of the plugin with a specific framework version. This approach was adopted from the `k8smeta` plugin.