Uploaded image for project: 'Core Server'
  1. Core Server
  2. SERVER-41858

mongocryptd can fail to produce an intent-to-encrypt marking for $redact

    • Type: Icon: Bug Bug
    • Resolution: Gone away
    • Priority: Icon: Critical - P2 Critical - P2
    • None
    • Affects Version/s: None
    • Component/s: Querying
    • ALL
    • v4.2
    • Hide

      Run the following script against mongocryptd:

      const jsonSchema = {
          type: "object",
          properties: {
              user: {
                  type: "object",
                  properties: {
                      ssn: {
                          encrypt: {
                              algorithm: "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic",
                              keyId: [UUID()],
                              bsonType: "string"
                          }
                      }
                  }
              }
          }
      };
      
      const pipeline =
          [{$redact: {$cond: {if: {$eq: ["$ssn", "123-45-6789"]}, then: "$$PRUNE", else: "$$DESCEND"}}}];
      
      printjson(db.runCommand({
          aggregate: "c",
          pipeline: pipeline,
          cursor: {},
          isRemoteSchema: false,
          jsonSchema: jsonSchema
      }));
      

      This produces the following output:

      {
      	"hasEncryptionPlaceholders" : false,
      	"schemaRequiresEncryption" : true,
      	"result" : {
      		"aggregate" : "c",
      		"pipeline" : [
      			{
      				"$redact" : {
      					"$cond" : [
      						{
      							"$eq" : [
      								"$ssn",
      								{
      									"$const" : "123-45-6789"
      								}
      							]
      						},
      						"$$PRUNE",
      						"$$DESCEND"
      					]
      				}
      			}
      		],
      		"cursor" : {
      
      		},
      		"lsid" : {
      			"id" : UUID("0506dff3-cdf4-4dde-afb3-d31221391d45")
      		}
      	},
      	"ok" : 1
      }
      

      The important thing to note is that the social security number in the query is not marked for encryption. The system would send it across the wire as plaintext.

      Since it is possible for the SSN in the query to be compared both to encrypted and unencrypted data, the correct behavior would be for mongocryptd to return an error.

      Show
      Run the following script against mongocryptd: const jsonSchema = { type: "object" , properties: { user: { type: "object" , properties: { ssn: { encrypt: { algorithm: "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" , keyId: [UUID()], bsonType: "string" } } } } } }; const pipeline = [{$redact: {$cond: { if : {$eq: [ "$ssn" , "123-45-6789" ]}, then: "$$PRUNE" , else : "$$DESCEND" }}}]; printjson(db.runCommand({ aggregate: "c" , pipeline: pipeline, cursor: {}, isRemoteSchema: false , jsonSchema: jsonSchema })); This produces the following output: { "hasEncryptionPlaceholders" : false , "schemaRequiresEncryption" : true , "result" : { "aggregate" : "c" , "pipeline" : [ { "$redact" : { "$cond" : [ { "$eq" : [ "$ssn" , { "$ const " : "123-45-6789" } ] }, "$$PRUNE" , "$$DESCEND" ] } } ], "cursor" : { }, "lsid" : { "id" : UUID( "0506dff3-cdf4-4dde-afb3-d31221391d45" ) } }, "ok" : 1 } The important thing to note is that the social security number in the query is not marked for encryption. The system would send it across the wire as plaintext. Since it is possible for the SSN in the query to be compared both to encrypted and unencrypted data, the correct behavior would be for mongocryptd to return an error.
    • Query 2019-07-01

      In SERVER-40832 we added client-side encryption support for the $redact aggregation stage. This works by simply calling into our regular aggregation expression analysis which marks agg expressions for encryption. This so intent-to-encrypt marking logic, however, always assumes that field paths are full paths with respect to $$ROOT. It does not account for the fact that during $redact's descent of an object, $$CURRENT is rebound such that $$CURRENT != $$ROOT. Therefore, field paths in $redact are not always full path starting from the root of the document. The consequence is that the analysis can fail to mark a constant for encryption. See "Steps to Reproduce" for an example.

      A quick fix for this problem would be to revert the changes in SERVER-40832. As a more complex fix, we could investigate whether it is possible to handle special cases in which we can statically prove that it is impossible for a comparison made in $redact to happen against both encrypted and unencrypted data.

            Assignee:
            arun.banala@mongodb.com Arun Banala
            Reporter:
            david.storch@mongodb.com David Storch
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: