From cb8496bbfef3ff314e6e95e5a9e2a9578d960975 Mon Sep 17 00:00:00 2001 From: Chanel Young Date: Wed, 16 Jul 2025 14:27:23 -0700 Subject: [PATCH 1/7] added queries, tests, docs --- .../BinaryFormatterDeserialization.qhelp | 37 ++++++++++++++++ .../cwe-502/BinaryFormatterDeserialization.ql | 23 ++++++++++ .../cwe-502/UnsafeDeserialization.qhelp | 37 ++++++++++++++++ .../security/cwe-502/UnsafeDeserialization.ql | 43 +++++++++++++++++++ .../BinaryFormatterDeserialization.ps1 | 6 +++ .../cwe-502/UnsafeDeserialization.expected | 1 + .../cwe-502/UnsafeDeserialization.qlref | 1 + .../query-tests/security/cwe-502/test.ps1 | 4 ++ 8 files changed, 152 insertions(+) create mode 100644 powershell/ql/src/queries/security/cwe-502/BinaryFormatterDeserialization.qhelp create mode 100644 powershell/ql/src/queries/security/cwe-502/BinaryFormatterDeserialization.ql create mode 100644 powershell/ql/src/queries/security/cwe-502/UnsafeDeserialization.qhelp create mode 100644 powershell/ql/src/queries/security/cwe-502/UnsafeDeserialization.ql create mode 100644 powershell/ql/src/queries/security/cwe-502/examples/BinaryFormatterDeserialization.ps1 create mode 100644 powershell/ql/test/query-tests/security/cwe-502/UnsafeDeserialization.expected create mode 100644 powershell/ql/test/query-tests/security/cwe-502/UnsafeDeserialization.qlref create mode 100644 powershell/ql/test/query-tests/security/cwe-502/test.ps1 diff --git a/powershell/ql/src/queries/security/cwe-502/BinaryFormatterDeserialization.qhelp b/powershell/ql/src/queries/security/cwe-502/BinaryFormatterDeserialization.qhelp new file mode 100644 index 00000000000..761560c4879 --- /dev/null +++ b/powershell/ql/src/queries/security/cwe-502/BinaryFormatterDeserialization.qhelp @@ -0,0 +1,37 @@ + + + + +

Using BinaryFormatter to deserialize an object from untrusted input may result in security problems, such +as denial of service or remote code execution.

+ +
+ + +

Avoid using BinaryFormatter.

+ +
+ + +

In this example, a string is deserialized using a +BinaryFormatter. BinaryFormatter is an easily exploited deserializer.

+ + + +
+ + +
  • +Muñoz, Alvaro and Mirosh, Oleksandr: +JSON Attacks. +
  • + +
  • +Microsoft: +Deserialization risks in use of BinaryFormatter and related types. +
  • + +
    +
    diff --git a/powershell/ql/src/queries/security/cwe-502/BinaryFormatterDeserialization.ql b/powershell/ql/src/queries/security/cwe-502/BinaryFormatterDeserialization.ql new file mode 100644 index 00000000000..78b74490df3 --- /dev/null +++ b/powershell/ql/src/queries/security/cwe-502/BinaryFormatterDeserialization.ql @@ -0,0 +1,23 @@ +/** + * @name Use of Binary Formatter deserialization + * @description Use of Binary Formatter is unsafe + * @kind problem + * @problem.severity error + * @security-severity 8.8 + * @precision high + * @id powershell/microsoft/public/binary-formatter-deserialization + * @tags correctness + * security + * external/cwe/cwe-502 + */ + +import powershell +import semmle.code.powershell.dataflow.DataFlow +import semmle.code.powershell.dataflow.TaintTracking + +from DataFlow::ObjectCreationNode source, DataFlow::CallNode cn +where +source.getExprNode().getExpr().(CallExpr).getAnArgument().getValue().asString() = "System.Runtime.Serialization.Formatters.Binary.BinaryFormatter" and +cn.getQualifier().getALocalSource() = source and +cn.getLowerCaseName() = "deserialize" +select cn, "Call to BinaryFormatter.Deserialize" diff --git a/powershell/ql/src/queries/security/cwe-502/UnsafeDeserialization.qhelp b/powershell/ql/src/queries/security/cwe-502/UnsafeDeserialization.qhelp new file mode 100644 index 00000000000..e8492ccbe9c --- /dev/null +++ b/powershell/ql/src/queries/security/cwe-502/UnsafeDeserialization.qhelp @@ -0,0 +1,37 @@ + + + + +

    Deserializing an object from untrusted input may result in security problems, such +as denial of service or remote code execution.

    + +
    + + +

    Avoid using an unsafe deserialization framework.

    + +
    + + +

    In this example, a string is deserialized using a +BinaryFormatter. BinaryFormatter is an easily exploited deserializer.

    + + + +
    + + +
  • +Muñoz, Alvaro and Mirosh, Oleksandr: +JSON Attacks. +
  • + +
  • +Microsoft: +Deserialization risks in use of BinaryFormatter and related types. +
  • + +
    +
    diff --git a/powershell/ql/src/queries/security/cwe-502/UnsafeDeserialization.ql b/powershell/ql/src/queries/security/cwe-502/UnsafeDeserialization.ql new file mode 100644 index 00000000000..e61e1da3a8e --- /dev/null +++ b/powershell/ql/src/queries/security/cwe-502/UnsafeDeserialization.ql @@ -0,0 +1,43 @@ +/** + * @name Unsafe deserializer + * @description Calling an unsafe deserializer with data controlled by an attacker + * can lead to denial of service and other security problems. + * @kind problem + * @problem.severity error + * @security-severity 8.8 + * @precision high + * @id powershell/microsoft/public/unsafe-deserialization + * @tags correctness + * security + * external/cwe/cwe-502 + */ + +import powershell +import semmle.code.powershell.dataflow.flowsources.FlowSources +import semmle.code.powershell.dataflow.DataFlow +import semmle.code.powershell.dataflow.TaintTracking + +module DeserializationConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source instanceof SourceNode } + + predicate isSink(DataFlow::Node sink) { + exists(DataFlow::ObjectCreationNode ocn, DataFlow::CallNode cn | + cn.getQualifier().getALocalSource() = ocn and + ocn.getExprNode().getExpr().(CallExpr).getAnArgument().getValue().asString() = "System.Runtime.Serialization.Formatters.Binary.BinaryFormatter" and + cn.getLowerCaseName() = "deserialize" and + cn.getAnArgument() = sink + ) + } + predicate isAdditionalFlowStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo){ + exists(InvokeMemberExpr ime | + nodeTo.asExpr().getExpr() = ime and + nodeFrom.asExpr().getExpr() = ime.getAnArgument() + ) + } +} + +module DeserializationFlow = TaintTracking::Global; + +from DataFlow::Node source, DataFlow::Node sink +where DeserializationFlow::flow(source, sink) +select sink, "Unsafe deserializer is used. Make sure the value being deserialized comes from a trusted source." diff --git a/powershell/ql/src/queries/security/cwe-502/examples/BinaryFormatterDeserialization.ps1 b/powershell/ql/src/queries/security/cwe-502/examples/BinaryFormatterDeserialization.ps1 new file mode 100644 index 00000000000..b222b1e5327 --- /dev/null +++ b/powershell/ql/src/queries/security/cwe-502/examples/BinaryFormatterDeserialization.ps1 @@ -0,0 +1,6 @@ +$untrustedBase64 = Read-Host "Enter user input" + +$formatter = New-Object System.Runtime.Serialization.Formatters.Binary.BinaryFormatter +$stream = [System.IO.MemoryStream]::new([Convert]::FromBase64String($untrustedBase64)) + +$obj = $formatter.Deserialize($stream) diff --git a/powershell/ql/test/query-tests/security/cwe-502/UnsafeDeserialization.expected b/powershell/ql/test/query-tests/security/cwe-502/UnsafeDeserialization.expected new file mode 100644 index 00000000000..2cdf339f6a1 --- /dev/null +++ b/powershell/ql/test/query-tests/security/cwe-502/UnsafeDeserialization.expected @@ -0,0 +1 @@ +| test.ps1:4:31:4:37 | stream | Unsafe deserializer is used. Make sure the value being deserialized comes from a trusted source. | diff --git a/powershell/ql/test/query-tests/security/cwe-502/UnsafeDeserialization.qlref b/powershell/ql/test/query-tests/security/cwe-502/UnsafeDeserialization.qlref new file mode 100644 index 00000000000..abfb453d723 --- /dev/null +++ b/powershell/ql/test/query-tests/security/cwe-502/UnsafeDeserialization.qlref @@ -0,0 +1 @@ +queries/security/cwe-502/UnsafeDeserialization.ql \ No newline at end of file diff --git a/powershell/ql/test/query-tests/security/cwe-502/test.ps1 b/powershell/ql/test/query-tests/security/cwe-502/test.ps1 new file mode 100644 index 00000000000..d35ef352cd3 --- /dev/null +++ b/powershell/ql/test/query-tests/security/cwe-502/test.ps1 @@ -0,0 +1,4 @@ +$untrustedBase64 = Read-Host "Enter user input" +$formatter = New-Object System.Runtime.Serialization.Formatters.Binary.BinaryFormatter +$stream = [System.IO.MemoryStream]::new([Convert]::FromBase64String($untrustedBase64)) +$obj = $formatter.Deserialize($stream) From 6ac935469fc94656fde83ce3822901da4894ee47 Mon Sep 17 00:00:00 2001 From: Chanel Young Date: Thu, 17 Jul 2025 08:27:36 -0700 Subject: [PATCH 2/7] move logic to qlls --- .../UnsafeDeserializationCustomizations.qll | 53 +++++++++++++++++++ .../security/UnsafeDeserializationQuery.qll | 28 ++++++++++ .../cwe-502/BinaryFormatterDeserialization.ql | 11 ++-- .../security/cwe-502/UnsafeDeserialization.ql | 39 ++++---------- 4 files changed, 95 insertions(+), 36 deletions(-) create mode 100644 powershell/ql/lib/semmle/code/powershell/security/UnsafeDeserializationCustomizations.qll create mode 100644 powershell/ql/lib/semmle/code/powershell/security/UnsafeDeserializationQuery.qll diff --git a/powershell/ql/lib/semmle/code/powershell/security/UnsafeDeserializationCustomizations.qll b/powershell/ql/lib/semmle/code/powershell/security/UnsafeDeserializationCustomizations.qll new file mode 100644 index 00000000000..25615acd77d --- /dev/null +++ b/powershell/ql/lib/semmle/code/powershell/security/UnsafeDeserializationCustomizations.qll @@ -0,0 +1,53 @@ +/** + * Provides default sources, sinks and sanitizers for reasoning about + * unsafe deserialization vulnerabilities, as well as extension points for + * adding your own. + */ + +private import semmle.code.powershell.dataflow.DataFlow +import semmle.code.powershell.ApiGraphs +private import semmle.code.powershell.dataflow.flowsources.FlowSources +private import semmle.code.powershell.Cfg + +module UnsafeDeserialization { + /** + * A data flow source for SQL-injection vulnerabilities. + */ + abstract class Source extends DataFlow::Node { + /** Gets a string that describes the type of this flow source. */ + abstract string getSourceType(); + } + + /** + * A data flow sink for SQL-injection vulnerabilities. + */ + abstract class Sink extends DataFlow::Node { + /** Gets a description of this sink. */ + abstract string getSinkType(); + + } + + /** + * A sanitizer for Unsafe Deserialization vulnerabilities. + */ + abstract class Sanitizer extends DataFlow::Node { } + + /** A source of user input, considered as a flow source for unsafe deserialization. */ + class FlowSourceAsSource extends Source instanceof SourceNode { + override string getSourceType() { result = SourceNode.super.getSourceType() } + } + + class BinaryFormatterDeserializeSink extends Sink { + BinaryFormatterDeserializeSink() { + exists(DataFlow::ObjectCreationNode ocn, DataFlow::CallNode cn | + cn.getQualifier().getALocalSource() = ocn and + ocn.getExprNode().getExpr().(CallExpr).getAnArgument().getValue().asString() = "System.Runtime.Serialization.Formatters.Binary.BinaryFormatter" and + cn.getLowerCaseName() = "deserialize" and + cn.getAnArgument() = this + ) + } + + override string getSinkType() { result = "call to BinaryFormatter.Deserialize" } + + } +} diff --git a/powershell/ql/lib/semmle/code/powershell/security/UnsafeDeserializationQuery.qll b/powershell/ql/lib/semmle/code/powershell/security/UnsafeDeserializationQuery.qll new file mode 100644 index 00000000000..fba30b507ad --- /dev/null +++ b/powershell/ql/lib/semmle/code/powershell/security/UnsafeDeserializationQuery.qll @@ -0,0 +1,28 @@ +/** + * Provides a taint tracking configuration for reasoning about + * deserialization vulnerabilities (CWE-502). + * + * Note, for performance reasons: only import this file if + * `UnsafeDeserializationFlow` is needed, otherwise + * `UnsafeDeserializationCustomizations` should be imported instead. + */ + +import powershell +import semmle.code.powershell.dataflow.flowsources.FlowSources +import semmle.code.powershell.dataflow.DataFlow +import semmle.code.powershell.dataflow.TaintTracking +import UnsafeDeserializationCustomizations::UnsafeDeserialization + +module Config implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source instanceof Source } + + predicate isSink(DataFlow::Node sink) { sink instanceof Sink } + predicate isAdditionalFlowStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo){ + exists(InvokeMemberExpr ime | + nodeTo.asExpr().getExpr() = ime and + nodeFrom.asExpr().getExpr() = ime.getAnArgument() + ) + } +} + +module UnsafeDeserializationFlow = TaintTracking::Global; \ No newline at end of file diff --git a/powershell/ql/src/queries/security/cwe-502/BinaryFormatterDeserialization.ql b/powershell/ql/src/queries/security/cwe-502/BinaryFormatterDeserialization.ql index 78b74490df3..c79f6ecda29 100644 --- a/powershell/ql/src/queries/security/cwe-502/BinaryFormatterDeserialization.ql +++ b/powershell/ql/src/queries/security/cwe-502/BinaryFormatterDeserialization.ql @@ -12,12 +12,7 @@ */ import powershell -import semmle.code.powershell.dataflow.DataFlow -import semmle.code.powershell.dataflow.TaintTracking +import semmle.code.powershell.security.UnsafeDeserializationCustomizations::UnsafeDeserialization -from DataFlow::ObjectCreationNode source, DataFlow::CallNode cn -where -source.getExprNode().getExpr().(CallExpr).getAnArgument().getValue().asString() = "System.Runtime.Serialization.Formatters.Binary.BinaryFormatter" and -cn.getQualifier().getALocalSource() = source and -cn.getLowerCaseName() = "deserialize" -select cn, "Call to BinaryFormatter.Deserialize" +from BinaryFormatterDeserializeSink sink +select sink, "Call to BinaryFormatter.Deserialize" diff --git a/powershell/ql/src/queries/security/cwe-502/UnsafeDeserialization.ql b/powershell/ql/src/queries/security/cwe-502/UnsafeDeserialization.ql index e61e1da3a8e..3713b0d5ed5 100644 --- a/powershell/ql/src/queries/security/cwe-502/UnsafeDeserialization.ql +++ b/powershell/ql/src/queries/security/cwe-502/UnsafeDeserialization.ql @@ -2,7 +2,7 @@ * @name Unsafe deserializer * @description Calling an unsafe deserializer with data controlled by an attacker * can lead to denial of service and other security problems. - * @kind problem + * @kind path-problem * @problem.severity error * @security-severity 8.8 * @precision high @@ -13,31 +13,14 @@ */ import powershell -import semmle.code.powershell.dataflow.flowsources.FlowSources -import semmle.code.powershell.dataflow.DataFlow -import semmle.code.powershell.dataflow.TaintTracking +import semmle.code.powershell.security.UnsafeDeserializationQuery +import UnsafeDeserializationFlow::PathGraph -module DeserializationConfig implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node source) { source instanceof SourceNode } - - predicate isSink(DataFlow::Node sink) { - exists(DataFlow::ObjectCreationNode ocn, DataFlow::CallNode cn | - cn.getQualifier().getALocalSource() = ocn and - ocn.getExprNode().getExpr().(CallExpr).getAnArgument().getValue().asString() = "System.Runtime.Serialization.Formatters.Binary.BinaryFormatter" and - cn.getLowerCaseName() = "deserialize" and - cn.getAnArgument() = sink - ) - } - predicate isAdditionalFlowStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo){ - exists(InvokeMemberExpr ime | - nodeTo.asExpr().getExpr() = ime and - nodeFrom.asExpr().getExpr() = ime.getAnArgument() - ) - } -} - -module DeserializationFlow = TaintTracking::Global; - -from DataFlow::Node source, DataFlow::Node sink -where DeserializationFlow::flow(source, sink) -select sink, "Unsafe deserializer is used. Make sure the value being deserialized comes from a trusted source." +from + UnsafeDeserializationFlow::PathNode source, UnsafeDeserializationFlow::PathNode sink, + Source sourceNode +where + UnsafeDeserializationFlow::flowPath(source, sink) and + sourceNode = source.getNode() +select sink.getNode(), source, sink, "This unsafe deserializer deserializes on a $@.", sourceNode, + sourceNode.getSourceType() From 1149d3369163c8cc10ef82be5c72f338ea3ead4b Mon Sep 17 00:00:00 2001 From: Chanel Young Date: Thu, 17 Jul 2025 13:19:07 -0700 Subject: [PATCH 3/7] updated .expected test file --- .../cwe-502/UnsafeDeserialization.expected | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/powershell/ql/test/query-tests/security/cwe-502/UnsafeDeserialization.expected b/powershell/ql/test/query-tests/security/cwe-502/UnsafeDeserialization.expected index 2cdf339f6a1..7476f52e567 100644 --- a/powershell/ql/test/query-tests/security/cwe-502/UnsafeDeserialization.expected +++ b/powershell/ql/test/query-tests/security/cwe-502/UnsafeDeserialization.expected @@ -1 +1,14 @@ -| test.ps1:4:31:4:37 | stream | Unsafe deserializer is used. Make sure the value being deserialized comes from a trusted source. | +edges +| test.ps1:1:20:1:47 | Call to read-host | test.ps1:3:69:3:84 | untrustedBase64 | provenance | Src:MaD:0 | +| test.ps1:3:11:3:86 | Call to new | test.ps1:4:31:4:37 | stream | provenance | | +| test.ps1:3:41:3:85 | Call to frombase64string | test.ps1:3:11:3:86 | Call to new | provenance | Config | +| test.ps1:3:69:3:84 | untrustedBase64 | test.ps1:3:41:3:85 | Call to frombase64string | provenance | Config | +nodes +| test.ps1:1:20:1:47 | Call to read-host | semmle.label | Call to read-host | +| test.ps1:3:11:3:86 | Call to new | semmle.label | Call to new | +| test.ps1:3:41:3:85 | Call to frombase64string | semmle.label | Call to frombase64string | +| test.ps1:3:69:3:84 | untrustedBase64 | semmle.label | untrustedBase64 | +| test.ps1:4:31:4:37 | stream | semmle.label | stream | +subpaths +#select +| test.ps1:4:31:4:37 | stream | test.ps1:1:20:1:47 | Call to read-host | test.ps1:4:31:4:37 | stream | This unsafe deserializer deserializes on a $@. | test.ps1:1:20:1:47 | Call to read-host | read from stdin | From 9266713d1987c2d80e0963a887c5a9018dfae27e Mon Sep 17 00:00:00 2001 From: Chanel <102255874+chanel-y@users.noreply.github.com> Date: Tue, 22 Jul 2025 10:06:39 -0700 Subject: [PATCH 4/7] Update powershell/ql/src/queries/security/cwe-502/BinaryFormatterDeserialization.qhelp Co-authored-by: Mathias Vorreiter Pedersen --- .../security/cwe-502/BinaryFormatterDeserialization.qhelp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powershell/ql/src/queries/security/cwe-502/BinaryFormatterDeserialization.qhelp b/powershell/ql/src/queries/security/cwe-502/BinaryFormatterDeserialization.qhelp index 761560c4879..bf7ad36e6d5 100644 --- a/powershell/ql/src/queries/security/cwe-502/BinaryFormatterDeserialization.qhelp +++ b/powershell/ql/src/queries/security/cwe-502/BinaryFormatterDeserialization.qhelp @@ -4,7 +4,7 @@ -

    Using BinaryFormatter to deserialize an object from untrusted input may result in security problems, such +

    Using BinaryFormatter to deserialize an object from untrusted input may result in security problems, such as denial of service or remote code execution.

    From 6d62e8717a83c8e451bda56099f87592e269eff9 Mon Sep 17 00:00:00 2001 From: Chanel <102255874+chanel-y@users.noreply.github.com> Date: Tue, 22 Jul 2025 10:06:46 -0700 Subject: [PATCH 5/7] Update powershell/ql/src/queries/security/cwe-502/BinaryFormatterDeserialization.qhelp Co-authored-by: Mathias Vorreiter Pedersen --- .../security/cwe-502/BinaryFormatterDeserialization.qhelp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powershell/ql/src/queries/security/cwe-502/BinaryFormatterDeserialization.qhelp b/powershell/ql/src/queries/security/cwe-502/BinaryFormatterDeserialization.qhelp index bf7ad36e6d5..7661adb40a0 100644 --- a/powershell/ql/src/queries/security/cwe-502/BinaryFormatterDeserialization.qhelp +++ b/powershell/ql/src/queries/security/cwe-502/BinaryFormatterDeserialization.qhelp @@ -10,7 +10,7 @@ as denial of service or remote code execution.

    -

    Avoid using BinaryFormatter.

    +

    Avoid using BinaryFormatter.

    From 2e93ec5490a348638c436b981e378f479f24c892 Mon Sep 17 00:00:00 2001 From: Chanel <102255874+chanel-y@users.noreply.github.com> Date: Tue, 22 Jul 2025 10:06:52 -0700 Subject: [PATCH 6/7] Update powershell/ql/src/queries/security/cwe-502/UnsafeDeserialization.qhelp Co-authored-by: Mathias Vorreiter Pedersen --- .../ql/src/queries/security/cwe-502/UnsafeDeserialization.qhelp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powershell/ql/src/queries/security/cwe-502/UnsafeDeserialization.qhelp b/powershell/ql/src/queries/security/cwe-502/UnsafeDeserialization.qhelp index e8492ccbe9c..26d5bda0600 100644 --- a/powershell/ql/src/queries/security/cwe-502/UnsafeDeserialization.qhelp +++ b/powershell/ql/src/queries/security/cwe-502/UnsafeDeserialization.qhelp @@ -16,7 +16,7 @@ as denial of service or remote code execution.

    In this example, a string is deserialized using a -BinaryFormatter. BinaryFormatter is an easily exploited deserializer.

    +BinaryFormatter. BinaryFormatter is an easily exploited deserializer.

    From 3b90949d4df73408145f9c010661dbb3142fd333 Mon Sep 17 00:00:00 2001 From: Chanel <102255874+chanel-y@users.noreply.github.com> Date: Tue, 22 Jul 2025 10:06:59 -0700 Subject: [PATCH 7/7] Update powershell/ql/src/queries/security/cwe-502/BinaryFormatterDeserialization.qhelp Co-authored-by: Mathias Vorreiter Pedersen --- .../security/cwe-502/BinaryFormatterDeserialization.qhelp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powershell/ql/src/queries/security/cwe-502/BinaryFormatterDeserialization.qhelp b/powershell/ql/src/queries/security/cwe-502/BinaryFormatterDeserialization.qhelp index 7661adb40a0..b54aff20bf5 100644 --- a/powershell/ql/src/queries/security/cwe-502/BinaryFormatterDeserialization.qhelp +++ b/powershell/ql/src/queries/security/cwe-502/BinaryFormatterDeserialization.qhelp @@ -16,7 +16,7 @@ as denial of service or remote code execution.

    In this example, a string is deserialized using a -BinaryFormatter. BinaryFormatter is an easily exploited deserializer.

    +BinaryFormatter. BinaryFormatter is an easily exploited deserializer.