Skip to main content
Ben Nadel at TechCrunch Disrupt (New York, NY) with: Aaron Foss and Mark C. Webster
Ben Nadel at TechCrunch Disrupt (New York, NY) with: Aaron Foss Mark C. Webster

Inspecting The Form Upload File Field Metadata In ColdFusion

By
Published in

When you upload a file in ColdFusion, the fileUpload() function and the CFFile[action=upload] tag aren't actually uploading the file to the server—at that point in the workflow, the file already exists on the server. The fileUpload() function is just moving the file from a temporary location to a permanent location of your choosing. And, when you're uploading files through a standard form post, the form field that represents your file upload contains the path to that temporary location. Which means you can therefore inspect a file in ColdFusion before you move it to its permanent location.

To see this in action, we're going to create a form that allows an image file to be uploaded. And, before we "upload" the file (vis-a-vis the fileUpload() function), we're going to get the size and dimensions of the given image while it's still in the server's temp directory.

Our form will only have a single field, imageFile; and, for the sake of simplicity, we're going to know that the form has been submitted by looking at the length of this field value. If it's populated, it means that it contains the path to the already-uploaded temporary file:

<cfscript>

	param name="form.imageFile" type="string" default="";

	// If the imageFile form field has a length, it contains the path to the file that has
	// already been uploaded into the server's temp directory. When you call fileUpload(),
	// or cffile[action=upload], you're not really uploading the file. More accurately,
	// you're just MOVING the file from a temporary location to a permanent location.
	if ( form.imageFile.len() ) {

		// Caution: All HTTP requests can be spoofed. Just because the form field has a
		// value in it, it doesn't mean that we can trust it. Make sure that the directory
		// that contains the temporary file is actually the expected directory.
		// --
		// Note: This is only meaningful when directly accessing the file in this type of
		// workflow. A fileUpload() workflow shouldn't require this type of check.
		if ( getDirectoryFromPath( getCanonicalPath( form.imageFile ) ) != getTempDirectory() ) {

			throw(
				type = "UnexpectedFileLocation",
				message = "Suspicious temporary file path."
			);

		}

		// Since we have access to the temporary file location, we can directly access the
		// file in order to gather metadata such as byte-size and, for images, dimensions.
		fileMetadata = {
			file: getFileInfo( form.imageFile ),
			image: imageInfo( imageNew( form.imageFile ) )
		};

	}

</cfscript>

<!doctype html>
<html lang="en">
<body>

	<h1>
		Upload An Image File
	</h1>

	<form method="post" enctype="multipart/form-data">
		<input
			type="file"
			name="imageFile"
			accept=".png, .jpg, .jpeg"
		/>
		<button type="submit">
			Upload Image
		</button>
	</form>

	<cfif ! isNull( fileMetadata )>
		<h2>
			File Metadata
		</h2>

		<cfdump
			var="#fileMetadata#"
			label="Uploaded File"
		/>
	</cfif>

</body>
</html>

Before I inspect the temporary file, I'm taking some security precautions to ensure that the given path exists in the server's temporary directory. Remember that every HTTP request can be spoofed by a malicious actor. Just because the form field contains a value, it doesn't inherently mean that it can be trusted. Normally, you wouldn't have to think about this check. But, since we're inspecting the file before we use ColdFusion's native upload functionality, it can't hurt to verify the location.

That said, you can see that I'm using the value of the form field to call the getFileInfo() and imageInfo() ColdFusion functions. And, when we run this Adobe ColdFusion page and look at the resultant data (for an uploaded image), we get the following output:

CFDump of the getFileInfo() and imageInfo() results in ColdFusion.

Notice that the path and source attributes in the getFileInfo() and imageInfo() results demonstrate that the file is being inspected while it's still residing within the server's temporary directory. This means that you can use this metadata to further restrict file uploads (such as blocking zero-length files) before even trying to call the fileUpload() function.

Now, to be clear, I still recommend that you ultimately use the fileUpload() function (or other related ColdFusion features) to move the uploaded file out of the temporary location. Those upload functions and tags apply additional security measures—such a blocking file extensions and validating mime-types—and provide information about the original file details.

Want to use code from this post? Check out the license.

Reader Comments

Post A Comment — I'd Love To Hear From You!

Post a Comment

I believe in love. I believe in compassion. I believe in human rights. I believe that we can afford to give more of these gifts to the world around us because it costs us nothing to be decent and kind and understanding. And, I want you to know that when you land on this site, you are accepted for who you are, no matter how you identify, what truths you live, or whatever kind of goofy shit makes you feel alive! Rock on with your bad self!
Ben Nadel