17584 Commits
Author SHA1 Message Date
Samuel Karp 7b48098d64 Merge pull request #13781 from abdul-khaliq-khalid/reference-reject-dotdot-path
reference: reject `..` path components that rewrite the host
2026-10-01 15:57:50 +00:00
syed abdul khaliq c20414b433 reference: reject .. path components that rewrite the host
Assisted-by: Claude
Signed-off-by: syed abdul khaliq <abdul@bugqore.com>
2026-10-01 12:14:49 +05:30
Samuel Karp 6e3030a6f2 releases: 1.7 EOL, update the rest to current
Signed-off-by: Samuel Karp <samuelkarp@google.com>
2026-09-30 16:33:37 -07:00
Samuel Karp df742f8d7e Merge pull request #14258 from vvoland/apparmor-sockets
contrib/apparmor: Deny AF_ALG and AF_VSOCK sockets in default container profile
2026-09-30 18:08:34 +00:00
Fu Wei fcb8ec6970 Merge pull request #14187 from NahumLitvin/proxy-snapshotter-default-timeout
snapshots/proxy: add optional default_timeout for proxy snapshotter calls
2026-09-30 13:19:41 +00:00
LEI WANG 20a3b31390 images: skip malformed digests when computing referrer labels
The child digest used to build the referrer GC label is taken from
an untrusted manifest and is not validated before the label key is
derived. A digest with an invalid algorithm separator or fewer than
12 hex characters previously panicked when sliced for the
".sha256." label suffix.

Validate the child digest and skip children whose digest is
malformed instead of panicking. The prefix length is kept in a
named constant, referrerLabelDigestLen.

Signed-off-by: LEI WANG <ssst0n3@gmail.com>
2026-09-30 17:51:26 +08:00
Paweł Gronowski 5e1373098a contrib/apparmor: Deny AF_VSOCK sockets in default container profile
The default seccomp profile excludes AF_VSOCK for direct socket calls,
but 32-bit x86 binaries can reach it through socketcall because
seccomp cannot inspect the pointer argument.

Deny the family in AppArmor so the socket_create LSM hook closes that
path and prevents default-profile containers from reaching host or
guest VSOCK services.

This mirrors moby/profiles commit b7711bef4ad769a13fd40fe1ba710ad0f796fcfd
("apparmor: Deny AF_VSOCK sockets in default container profile").

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2026-09-29 17:47:10 +02:00
Paweł Gronowski 29f1191f5d contrib/apparmor: Deny AF_ALG sockets in default container profile
The AF_ALG address family exposes the Linux kernel crypto API to
userspace via sockets. This has been a source of container escape
vulnerabilities (see https://copy.fail/).

Unlike seccomp, which can only filter arguments of the direct
socket(2) syscall, AppArmor hooks into the kernel's
security_socket_create() LSM callback, which fires regardless of the
syscall entry point. This means AppArmor also blocks AF_ALG sockets
created via the legacy socketcall(2) multiplexer (used by 32-bit
binaries), which seccomp cannot inspect because the address family is
behind a userspace pointer that BPF cannot dereference.

The "deny network alg," rule is placed right after the blanket
"network," allow rule so the deny takes precedence for this specific
address family.

This mirrors moby/profiles commit 946fe8e08d9debcafe76ee60d69261a0c0990368
("apparmor: Deny AF_ALG sockets in default container profile").

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2026-09-29 17:46:54 +02:00
Nahum Litvin 2a843ba567 snapshots/proxy: add optional default_timeout for proxy snapshotter calls
A proxy snapshotter is a separate process, and none of its 10 gRPC
methods carry a deadline unless the caller already set one. Snapshot GC
calls Walk and Remove under the snapshotter-level lock, so one wedged
call blocks every later mutating call on that snapshotter.

Add default_timeout to the proxy_plugins config section. When set, each
proxy snapshotter call gets that deadline if the incoming context has
none; a context that already carries its own deadline is left alone.
Empty or unset keeps today's behavior, so nothing changes for existing
configs.

NewSnapshotter keeps its signature and wraps the new
NewSnapshotterWithOpts, so existing callers of the exported constructor
are unaffected.

Assisted-by: Claude Code
Signed-off-by: Nahum Litvin <nahuml@wix.com>
2026-09-29 12:17:26 +01:00
Samuel Karp cf413d5d96 Merge pull request #14245 from vvoland/seccomp-allowlist
seccomp: Use an allow-list for socket domains
2026-09-28 21:06:03 +00:00
Samuel Karp bb12c26a17 Merge pull request #14234 from containerd/dependabot/go_modules/k8s-809a0ec50e
build(deps): bump the k8s group with 2 updates
2026-09-28 17:04:41 +00:00
Samuel Karp 59829d6050 Merge pull request #14233 from containerd/dependabot/github_actions/docker-actions-b530e7f9d1
build(deps): bump docker/setup-buildx-action from 4.3.0 to 4.4.1 in the docker-actions group
2026-09-28 17:04:21 +00:00
Maksym Pavlenko e23c4a301e Merge pull request #14236 from containerd/dependabot/go_modules/google.golang.org/grpc-1.84.0
build(deps): bump google.golang.org/grpc from 1.83.2 to 1.84.0
2026-09-28 17:00:37 +00:00
Paweł Gronowski 03d46bb397 seccomp: Use an allow-list for socket domains
The default profile allowed socket(2) through open-ended range checks
around AF_ALG and AF_VSOCK. Any address family added to Linux later was
allowed automatically.

List the Linux address families the default profile supports and build
the socket rules from that list.

AF_ALG and AF_VSOCK stay blocked, and unknown or future domains now get
the default EPERM response.

A single rule cannot bound both ends of a range, because runc treats
repeated comparisons on one argument as OR.

The consecutive run starting at AF_UNIX therefore becomes one less-than
rule, which is safe because AF_UNSPEC cannot be created. Every other
domain gets its own equality rule.

This matches the same change in Moby's default seccomp profile.

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2026-09-28 17:31:21 +02:00
Akihiro Suda 04f9be90bd Merge pull request #14231 from thaJeztah/bump_runc
update runc binary to v1.5.2
2026-09-27 07:14:53 +00:00
Maksym Pavlenko 934434dde5 Merge pull request #14232 from samuelkarp/conditional-actions
Conditional actions
2026-09-25 23:47:45 +00:00
dependabot[bot] 0e335b8e68 build(deps): bump google.golang.org/grpc from 1.83.2 to 1.84.0
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.83.2 to 1.84.0.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.83.2...v1.84.0)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-version: 1.84.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-09-25 23:23:26 +00:00
dependabot[bot] e18b2bf601 build(deps): bump the k8s group with 2 updates
Bumps the k8s group with 2 updates: [k8s.io/cri-api](https://github.com/kubernetes/cri-api) and [k8s.io/streaming](https://github.com/kubernetes/streaming).


Updates `k8s.io/cri-api` from 0.37.0 to 0.37.1
- [Commits](https://github.com/kubernetes/cri-api/compare/v0.37.0...v0.37.1)

Updates `k8s.io/streaming` from 0.37.0 to 0.37.1
- [Commits](https://github.com/kubernetes/streaming/compare/v0.37.0...v0.37.1)

---
updated-dependencies:
- dependency-name: k8s.io/cri-api
  dependency-version: 0.37.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: k8s
- dependency-name: k8s.io/streaming
  dependency-version: 0.37.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: k8s
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-09-25 23:22:53 +00:00
dependabot[bot] 4f1c1c17e8 build(deps): bump docker/setup-buildx-action in the docker-actions group
Bumps the docker-actions group with 1 update: [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action).


Updates `docker/setup-buildx-action` from 4.3.0 to 4.4.1
- [Release notes](https://github.com/docker/setup-buildx-action/releases)
- [Commits](https://github.com/docker/setup-buildx-action/compare/37fe631027851001ddb9b187196cc803df7f5f0e...f87e5991a6d7451dcb8d9637bfbc97413f497069)

---
updated-dependencies:
- dependency-name: docker/setup-buildx-action
  dependency-version: 4.4.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: docker-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-09-25 23:22:46 +00:00
Maksym Pavlenko b26d2ba238 Merge pull request #14137 from thaJeztah/perfsprint
golangci-lint: enable perfsprint linter
2026-09-25 22:49:59 +00:00
Samuel Karp 3343c9c74a Makefile: remove go mod download from integration
Commit 192168038e removed the separate integration/client Go module
and merged its dependencies into the root module and vendor directory.
Running `go mod download` before `go test` in integration/client is
unnecessary because `go test` uses the root vendor directory.

Assisted-by: Antigravity
Signed-off-by: Samuel Karp <samuelkarp@google.com>
2026-09-25 15:37:45 -07:00
Samuel Karp 798aacc485 ci: skip linters steps in private repositories
Skip the linters steps when running in private repositories while
allowing the job itself to succeed so downstream jobs with
`needs: [..., linters, ...]` still run. Exclude macos-latest and
windows-latest from the linters matrix on private repositories to
avoid starting unnecessary runners.

Assisted-by: Antigravity
Signed-off-by: Samuel Karp <samuelkarp@google.com>
2026-09-25 15:37:34 -07:00
Samuel Karp 2e10f3195b workflows: skip non-CI jobs in private forks
Private forks of containerd are used for validating security patches
ahead of public disclosure. Some jobs should not run in that context.

Guard pull_request and push jobs with !github.event.repository.private
so they continue to run on containerd/containerd and public forks.
Because schedule events do not populate github.event.repository, guard
scheduled runs in nightly.yml and scorecards.yml with
github.repository == 'containerd/containerd'.

Assisted-by: Antigravity
Signed-off-by: Samuel Karp <samuelkarp@google.com>
2026-09-25 15:36:19 -07:00
Sebastiaan van Stijn 87f2e7e318 update runc binary to v1.5.2
This is the second patch release in the 1.5.z release series of runc,
which primarily includes a workaround for a Linux kernel bug causing
random runc crashes when using cgroup v2, and other fixes.

Fixed

- `runc exec -p` with a `process.json` lacking env now sets HOME again (a regression in runc 1.3.0).
- Worked around a Linux kernel bug (present since kernel v6.17, fixed in v7.2)
  which caused the kernel to write past the end of the structure
  provided by userspace (runc). This resulted in memory corruption inside runc
  (manifesting as random crashes) when configuring device rules on cgroup v2
  systems.
- `runc exec --cgroup` (and the equivalent libcontainer `Process.SubCgroupPaths`
  API) no longer accepts a sub-cgroup path that escapes the container's cgroup
  into a sibling cgroup sharing the same name prefix. Note that using
  `--cgroup` requires the same privileges as running runc exec itself, so
  this is a correctness rather than a security fix.
- Fixed a missing `O_CLOEXEC` when opening the cgroup v2 directory to set up
  device rules.
- Some long-standing file-descriptor leaks on the eBPF devices cgroups were
  fixed.
- When rootfsPropagation is set to `rslave`, the rootfs parent mount is no
  longer made private before pivoting into the rootfs, so unmount/remount
  events on host mountpoints under the rootfs are now propagated to the
  running container.
- runc no longer misdetects a non-initial user namespace as the initial one
  when that namespace has a full identity ID mapping (0 0 4294967295), as
  used by systemd >= 260 units with `PrivateUsers=full`. Previously this made
  runc skip its user namespace code paths, so starting a container in such a
  unit failed with `bpf_prog_query(BPF_CGROUP_DEVICE) failed: operation not permitted`.
- Fixed a runc init panic (`SIGABRT`) on the error path, caused by SELinux
  labels being reset after the cached libpathrs procfs handle was already
 closed. This is fixed both by not resetting the labels on the init error
  path, and by updating to libpathrs v0.2.6, which now handles a closed
  procfs handle gracefully.
- Fixed various issues when the libseccomp version runc is run with differs
  from the one it was compiled against (e.g. built with libseccomp >= 2.6.0 and
  run with an older one), by updating to libseccomp-golang v0.12.0. This also
  supersedes the `SECCOMP_FILTER_FLAG_WAIT_KILLABLE_RECV` workaround added in
  runc 1.5.1.
- The libseccomp library statically linked into release binaries is now built
  with optimizations enabled (the default `-g -O2 CFLAGS`); previously it was
  built unoptimized.

Changed

- Switched to opencontainers/cgroups v0.1.0, which no longer uses the
  high-level cilium/ebpf API to manage cgroup v2 device rules. As a result,
  the runc binary shrunk by about 1 MiB (7.5%) on amd64. This also means runc
  no longer calls the cilium/ebpf code affected by GO-2026-6238.
- Updated golang.org/x/net to v0.55.0.
- Updated builds to libseccomp v2.6.1.

release-notes: https://github.com/opencontainers/runc/releases/tag/v1.5.2
full diff: https://github.com/opencontainers/runc/releases/compare/v1.5.1...v1.5.2

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-09-25 21:47:13 +02:00
Samuel Karp 82f33ce76d Merge commit from fork 2026-09-24 14:44:56 -07:00
Maksym Pavlenko b450304e54 Merge pull request #14218 from mxpv/leak
cri: don't leak task when StartContainer cleanup fails to delete task
2026-09-24 19:09:38 +00:00
Mike Brown a6f16396bc Merge pull request #14221 from mxpv/kep
Add Maksym to CRI KEP issue template
2026-09-24 17:56:40 +00:00
Maksym Pavlenko 863b9f3eed Add Maksym to CRI KEP issue template
Signed-off-by: Maksym Pavlenko <pavlenko.maksym@gmail.com>
2026-09-24 10:03:29 -07:00
Maksym Pavlenko bafdeed1dc cri: fix process leak when start cleanup fails to delete task
When StartContainer fails after the task is created and the cleanup
task delete fails (e.g. it timed out on a stuck shim), the container
was still recorded as EXITED while its task remained. RemoveContainer
only reaps tasks for RUNNING and UNKNOWN containers, so every kubelet
GC retry failed with "cannot delete running task" and the container
was never collected. Record the container as UNKNOWN when task cleanup
cannot be confirmed so RemoveContainer force-stops it and retries the
cleanup, keeping the StartError reason in both cases.

Signed-off-by: Maksym Pavlenko <pavlenko.maksym@gmail.com>
2026-09-24 09:55:11 -07:00
Maksym Pavlenko e210d8492d Merge pull request #14217 from samuelkarp/ctr-stop-on-nth-arg
ctr: preserve args after "-" in images export
2026-09-24 00:41:50 +00:00
Samuel Karp 72c741e0a8 ctr: preserve args after "-" in images export
urfave/cli/v3 breaks out of its flag parsing loop when it encounters a
"-" positional argument without appending the remaining arguments,
causing "ctr images export - <image>" to drop all image references and
flags following "-".

When <out> is "-", recover the un-truncated arguments from the parent
"images" command lineage and re-parse the tail starting at "-" with a
sentinel placeholder so trailing image references and flags are
preserved.

This workaround can be removed after the bug is fixed upstream:

* https://github.com/urfave/cli/issues/2418
* https://github.com/urfave/cli/pull/2419

Assisted-by: Antigravity
Signed-off-by: Samuel Karp <samuelkarp@google.com>
2026-09-23 16:51:47 -07:00
Samuel Karp 5c4dc96e8e Merge pull request #14209 from samuelkarp/ctr-stop-on-nth-arg
ctr: fix flag parsing issues in run, containers create, tasks exec, and oci-hook
2026-09-23 20:29:41 +00:00
Maksym Pavlenko 21dc292bbf Merge pull request #14201 from containerd/shim_telemetry
Use stable OpenTelemetry shim service name
2026-09-23 19:05:11 +00:00
Samuel Karp 0250b9312f cmd/containerd: stop flag parsing on oci-hook
"containerd oci-hook" defines no flags of its own and passes all
arguments directly to the target hook binary via syscall.Exec. Set
StopOnNthArg to 1 so urfave/cli/v3 stops flag parsing after the hook
binary path while still stripping an optional "--" separator.

Assisted-by: Antigravity
Signed-off-by: Samuel Karp <samuelkarp@google.com>
2026-09-23 10:23:29 -07:00
Samuel Karp 334d6daceb ctr: stop flag parsing before container command
urfave/cli/v3 scans for flags across all positional arguments by
default, which causes flags meant for the container process to be
parsed as ctr flags.

Configure StopOnNthArg to stop flag parsing before the container
command and its arguments:
- "ctr run" and "ctr containers create": after Image|RootFS and
  CONTAINER (2 args)
- "ctr tasks exec": after CONTAINER (1 arg)

Fixes #14208

Assisted-by: Antigravity
Signed-off-by: Samuel Karp <samuelkarp@google.com>
2026-09-23 10:23:17 -07:00
Phil Estes afd5e93774 Merge pull request #14189 from mxpv/upgrade-tests
Drop upgrade tests from 1.7, add 2.3 and 2.4
2026-09-23 17:19:30 +00:00
Phil Estes 9eb6daf249 Merge pull request #14207 from liunan-ms/liunan/cri-wrapped-enotsup-relabel
cri: tolerate wrapped ENOTSUP during relabel
2026-09-23 15:57:02 +00:00
Nan Liu f42cf4504d cri: tolerate wrapped ENOTSUP during relabel
label.Relabel can return a PathError wrapping ENOTSUP. Use errors.Is so the existing unsupported-filesystem tolerance also handles wrapped errors.

Signed-off-by: Nan Liu <liunan@microsoft.com>
2026-09-22 23:31:41 +00:00
Chris Henzie 4f5f32636d Bound Walk references
Return an error wrapping ErrResourceExhausted when the walk exceeds
10,000 references. Preserve duplicate visits and count every reference
toward the limit across recursive calls and roots.

Assisted-by: Claude Code
Signed-off-by: Chris Henzie <chrishenzie@gmail.com>
2026-09-22 09:09:56 -07:00
Chris Henzie 94e83c14c8 Bound Dispatch concurrency and references
Traverse breadth-first, one level at a time. Acquire the limiter before
starting each handler goroutine. Default to 32 concurrent handlers when
no limiter is provided. Children wait until every handler in the current
level finishes.

Preserve duplicate visits and return an error wrapping
ErrResourceExhausted when the traversal exceeds 10,000 references.
Count children as handlers return them to bound the descriptors retained
for the next level.

Assisted-by: Claude Code
Signed-off-by: Chris Henzie <chrishenzie@gmail.com>
2026-09-22 09:09:56 -07:00
Maksym Pavlenko 645bab53e7 docs: describe runc shim tracing identity
Document the shim_tracing build tag, the stable service name, and the instance
ID and version resource attributes. Explain inherited attribute handling,
instance ID scope, and migration from the previous per-shim service names.

Signed-off-by: Maksym Pavlenko <pavlenko.maksym@gmail.com>
2026-09-21 13:39:43 -07:00
Maksym Pavlenko ee45bc3333 shim: use a stable OpenTelemetry service name
Use containerd-shim-runc-v2 as the service name and report the supplied shim ID
and build version through service.instance.id and service.version. Preserve
inherited resource attributes while overriding the shim identity fields.

Test resource decoding and inherited attribute precedence with the OpenTelemetry
SDK.

Signed-off-by: Maksym Pavlenko <pavlenko.maksym@gmail.com>
2026-09-21 13:39:43 -07:00
Samuel Karp 5152cb5d53 Merge pull request #13855 from aysha-afrah26/unpack-strip-idmap-labels
core/unpack: don't honor id-mapping labels from image annotations
2026-09-21 19:25:10 +00:00
Maksym Pavlenko b0a37b632b Merge pull request #14195 from containerd/dependabot/github_actions/azure/login-3.1.0
build(deps): bump azure/login from 3.0.2 to 3.1.0
2026-09-19 22:49:48 +00:00
Maksym Pavlenko 00d47249da Merge pull request #14194 from crazy-max/fix-fetch-retry-after-eof
remotes: revert closing fetch readers at EOF
2026-09-19 19:48:59 +00:00
dependabot[bot] 5850b2a4dc build(deps): bump azure/login from 3.0.2 to 3.1.0
Bumps [azure/login](https://github.com/azure/login) from 3.0.2 to 3.1.0.
- [Release notes](https://github.com/azure/login/releases)
- [Commits](https://github.com/azure/login/compare/7ddb5af1ef8758cf1353cf3b42f940aee27ba21c...a641126d1b8aa4d1fa005f4f92df94a3a4c4c906)

---
updated-dependencies:
- dependency-name: azure/login
  dependency-version: 3.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-09-18 23:23:22 +00:00
CrazyMax 0bdad4667c remotes: test fetch retries and HTTP reader lifetime
Verify that small and large layer uploads can be replayed after the registry consumes the body and returns HTTP 408.
This covers the fetch-to-pusher path used by BuildKit registry cache exports.

Check that HTTP readers close their response bodies at EOF while remaining seekable, and that the body is closed
exactly once before the destination writer commits.

Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
2026-09-19 00:43:32 +02:00
CrazyMax 4783451c96 Revert "remotes: close fetch reader immediately on EOF"
This reverts commit a989093a9c.

Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
2026-09-19 00:42:16 +02:00
Maksym Pavlenko e4e83b3af8 integration: test upgrades from 2.3 and 2.4
With 1.7 gone the matrix was left testing only 2.0, which is neither the
current LTS nor the release immediately preceding main. RELEASES.md
promises two paths into a given release: a sequential minor upgrade and a
sequential LTS upgrade. For main those are 2.4 and 2.3 respectively, so
test both.

Switch the download to the static release tarball. Release binaries are
built on Ubuntu 22.04, and the dynamically linked containerd from 2.3 on
needs GLIBC_2.32 and GLIBC_2.34. The EL8 hosts kept in the VM
integration matrix for their old glibc only have 2.28, so the previous
release never started there and every case timed out waiting for it. The
2.0 binaries needed nothing newer than GLIBC_2.4, which is why the old
matrix did not hit this. The static build has no libc dependency, and
its shim is the same binary the dynamic tarball already shipped.

Also bump the previous-release config to version 3. Version 2 only
mattered while 1.x was in the matrix, and every release now under test
writes version 3 by default.

kill-shim-before-delete-task needs its expected exit status picked per
version. Once the shim has been killed, containerd reports whatever
`<shim> delete` returns, and manager.Stop prefers the exit status
recorded in the bundle, falling back to a synthesized SIGKILL status when
there is no record. Recording landed in v2.4.0, so a bundle left by 2.3
reports 128+SIGKILL while one left by 2.4 reports the status the task
actually exited with. The old matrix predated recording entirely and only
ever covered the fallback; keying the expectation off the previous
version covers both branches.

Signed-off-by: Maksym Pavlenko <pavlenko.maksym@gmail.com>
2026-09-17 16:22:26 -07:00
Maksym Pavlenko 35105fc2f0 integration: drop upgrade tests from 1.7
containerd 2.4 is released, and per the documented upgrade path in
RELEASES.md a direct upgrade is only supported between sequential minor
releases or between sequential LTS releases. 1.7 (LTS) -> 2.3 (LTS) is
the last supported jump out of 1.7, so main no longer needs to test it.

Remove the 1.7 arm of TestUpgrade along with the cases that only ever
ran for it:

- recover-ungroupable-shim, which needed the runcv1 runtime handler and
  the pre-existing-config variant of the test harness.
- should-address-shim-version-mismatches, which covered the task v2
  bootstrap.json downgrade done for 1.7 shims.
- TestIssue10467, which pinned v1.7.20 to verify the sandbox bucket
  migration.

With those gone, oneSevenCtrdConfig, the usingExistingConfig plumbing
and the runtime handler parameter are all unused, so drop them too.

Signed-off-by: Maksym Pavlenko <pavlenko.maksym@gmail.com>
2026-09-17 14:18:28 -07:00