Docs / Detectors / Modern Deserialization

Modern Deserialization V33 · v1.6

Request bodies that look like serialized-object payloads for runtimes where deserialization equals code execution. Detection-only, because a forgiving parser will still deserialize the remainder if you strip the head bytes. The caller chooses how to refuse.

What it catches

Head-byte markers take precedence over embedded markers (byte-precise wins over substring).

Sample

import { detectDeserialization, isSerializedPayload } from '@arcis/node';

const runtime = detectDeserialization(body_string);
// "python_pickle" | "java_fastjson" | "php_unserialize" | "ruby_marshal" | "dotnet_binary_formatter" | null

if (runtime) {
  res.status(400).json({ error: 'serialized payload not allowed', runtime });
  return;
}

// Or simpler: just check the boolean
if (isSerializedPayload(body_string)) {
  res.status(400).send();
}

Configuration

No options. The function is a pure marker check. Run it on every endpoint that accepts a string body before any deserialization library touches the content.

When you actually do want serialization

If your endpoint legitimately accepts pickle (a Python-only RPC channel, for instance), do not call this detector on that route. The detector is a per-route opt-in, not a global middleware.

References

Refuse, do not strip. Detection only. A forgiving deserializer might still parse the remainder of a payload after the magic bytes are removed. The caller has to refuse the request; sanitization is not safe for this class.