The SafeCtl.exe sample demonstrates how to modify an MFC-based ActiveX control to indicate who published the code and whether a control has been tampered with. The sample can help to identify whether the control is safe for scripting and safe for initialization.
The following file is available for download from the Microsoft Download Center:
For more information about how to download Microsoft support files, click the following article number to view the article in the Microsoft Knowledge Base:
How to obtain Microsoft support files from online services
Microsoft scanned this file for viruses. Microsoft used the most current virus-detection software that was available on the date that the file was posted. The file is stored on security-enhanced servers that help prevent any unauthorized changes to the file.
In Internet Explorer 3.0 and later versions, users can add code in the form of ActiveX controls to their Web pages. The <OBJECT> tag is used to specify a control. After an instance of the control is created, its attributes can be set through the control's persistence interfaces. For example, for each <PARAM> tag that Internet Explorer encounters in the context of an <OBJECT> tag while parsing an HTML page, Internet Explorer passes a property bag through the corresponding control's IPersistPropertyBag
interface. Furthermore, the behavior of a control can be customized through the use of scripts embedded in the page that execute the methods and modify the properties exposed through the control's automation interface.
Authenticode code signing technology allows end users to identify who published the code and to verify that no one has tampered with that code since it was signed. It does not guarantee that the code is safe when its properties are initialized with untrusted values or when its automation model is driven by untrusted scripts. To avoid such potential security hazards, the default Internet Explorer security settings, which are accessible via the Security
tab of the Internet Explorer Options
property sheet, require that a control register itself as implementing the appropriate component categories or that the control implement the IObjectSafety
interface. The sample illustrates both.
Before it sets the properties of a control embedded in an HTML page, Internet Explorer queries the control for IObjectSafety
. If supported, Internet Explorer then calls the SetInterfaceSafetyOptions
method on this interface, passing the value INTERFACESAFE_FOR_UNTRUSTED_DATA as well as the interface identifier (IID) of a persistence interface. On HTML pages today, where properties tend to be initialized via the <PARAM> tag, the IID is IID_IPersistPropertyBag. The IID is provided for situations where you might want to be protect the safety on some interfaces but not on others, and in this example that is not important. The sample implementation checks to make sure that the interface is supported. If the control can do no harm to the client's system regardless of the data with which it may be initialized through that persistence interface and that persistence interface is supported, the control's implementation of the IObjectSafety::SetInterfaceSafetyOptions
method should return S_OK. Otherwise, E_FAIL should be returned.
Before allowing any scripts that are embedded in the page to be run, Internet Explorer similarly calls through the control's IObjectSafety:: SetInterfaceSafetyOptions
method but instead passes the value INTERFACESAFE_FOR_UNTRUSTED_CALLER and the IID of some scripting interface, which typically is IID_IDispatch. The control should return S_OK or E_FAIL appropriately.
If the control does not support IObjectSafety
, Internet Explorer uses the component categories manager to see if the control implements the "safe for initialization" category, CATID_SafeForInitializing, and the "safe for scripting" category, CATID_SafeForScripting, respectively.
If the control does not support IObjectSafety
and has not registered itself as implementing the appropriate component categories, and if the Internet Explorer safety level is set to High, the default, Internet Explorer will not initialize the control's properties, nor will it execute any scripts that are embedded in the page. In this scenario, end users receive a dialog box that contains the following text:
Potential safety violation avoided
This page contains active content that is not verifiably safe to display. To protect your computer, this content will not be displayed.
The following is a list of guidelines that are taken from Paul Johns' article, "Signing and Marking ActiveX Controls:"
- The control does not manipulate the file system.
- The control does not manipulate the registry (except to register and to unregister itself).
- The control does not overindex arrays or otherwise manipulate memory incorrectly.
- The control validates (and corrects) all input, including initialization, method parameters, and property set functions.
- The control does not misuse any data that is provided by the user or that is about that user.
- The control was tested in a variety of scenarios.
For additional information, visit the following Microsoft Web site:
If a control author has verified that the above criteria have been met in addition to any others that they can think of, they should consider supporting both IObjectSafety
and registering their control as implementing the appropriate component categories. For a list of the advantages and disadvantages of each of these methods, review the corresponding section in Paul Johns' article, "Signing and Marking ActiveX Controls."
Building the sample requires Microsoft Visual C++ 5.0 or Microsoft Visual C++ 6.0. After you extract the files from the archive, load the Safectl.mdp project into Microsoft Developer Studio, and build the project. As part of the build process, the control should register itself.Warning
Before you modify the sample by using the two preprocessor symbols that are listed later in this section, you have to unregister the control if it has already been built or registered on the computer. To do this, run Regsvr32.exe with the /u
switch for your control. You can also add a custom tool entry in Developer Studio that will do this for the current project. On the Tools
menu, click Customize
, and then click the Tools
tab. Create a new entry with the following information:
Name: &Un-register ActiveX Control Command: e:\Program Files\DevStudio\SharedIDE\BIN\REGSVR32.EXE Arguments: /u /v "$(TargetPath)" Initial Directory: $(TargetDir)
At this point, you can use the "tools/Un-register ActiveX Control" entry to unregister your control before you add or remove the sample-specific preprocessor definitions.
To build the control so that it registers itself as implementing the "safe for initializing" and the "safe for scripting" component categories, follow these steps:
- On the Project menu, click Settings.
- Click the C++ tab, and then define the following preprocessor definition:
- Click OK to close the Settings dialog box, and then rebuild the control.
To build the control so that it instead implements IObjectSafety
, follow the previous steps, but replace L_USE_COMCAT with L_IMPL_OBJECTSAFETY.
It is also valid to define both preprocessor symbols. Observe that these symbols are specific to this project. By default, the build settings of the project define both preprocessor symbols.
After the sample control has been built and has been registered successfully, start Internet Explorer, and then open the Safectl.htm page, which is included with the sample.
If the control has been configured to register itself as safe or implement IObjectSafety
, the controls caption should read "Safe for initializing!" When you click the control, you should receive the following message:
I must be safe for scripting!
If Internet Explorer is set to its highest safety setting, the associated script does not run, and you receive the following message:
NOT safe for initializing!Note
If you are building and testing different configurations of this sample, make sure that you refresh the Web page in the browser. If you do not refresh the page, you may be using the cached version of the control instead of the latest build.