Repository: oasis-open/cti-stix-validator

Issue:
warn instead of error for SHOULD
When providing a custom property, it errors about it (prints in red), instead of warning about it.
[!] course-of-action--d6e1dbd5-104f-4a09-b76c-3531d3398ecb: {103} Custom property 'obs_ref' should have a type that starts with 'x_' followed by a source unique identifier (like a domain name with dots replaced by dashes), a dash and then the name.

Discussion:

Patch:
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index b3ce782..1f505a8 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,42 +1,27 @@
-<div>
-<h1>Contributing</h1>
+# Contributing
 
-<div>
-<h2><a id="openParticipation">Public Participation Invited</a></h2>
+## <a id="openParticipation">Public Participation Invited</a>
 
-<p>This <a href="https://www.oasis-open.org/resources/open-repositories">OASIS Open Repository</a> ( <b><a href="https://github.com/oasis-open/cti-stix-validator">github.com/oasis-open/cti-stix-validator</a></b> ) is a community public repository that supports participation by anyone, whether affiliated with OASIS or not.  Substantive contributions (repository "code") and related feedback is invited from all parties, following the common conventions for participation in GitHub public repository projects.  Participation is expected to be consistent with the <a href="https://www.oasis-open.org/policies-guidelines/open-repositories">OASIS Open Repository Guidelines and Procedures</a>, the <a href="https://www.oasis-open.org/sites/www.oasis-open.org/files/BSD-3-Clause.txt">LICENSE</a> designated for this particular repository (BSD-3-Clause License), and the requirement for an <a href="https://www.oasis-open.org/resources/open-repositories/cla/individual-cla">Individual Contributor License Agreement</a>.  Please see the repository <a href="https://github.com/oasis-open/cti-stix-validator/blob/master/README.md">README</a> document for other details.</p>
-</div>
+This [OASIS Open Repository](https://www.oasis-open.org/resources/open-repositories) ( **[github.com/oasis-open/cti-stix-validator](https://github.com/oasis-open/cti-stix-validator)** ) is a community public repository that supports participation by anyone, whether affiliated with OASIS or not. Substantive contributions (repository "code") and related feedback is invited from all parties, following the common conventions for participation in GitHub public repository projects. Participation is expected to be consistent with the [OASIS Open Repository Guidelines and Procedures](https://www.oasis-open.org/policies-guidelines/open-repositories), the [LICENSE](https://www.oasis-open.org/sites/www.oasis-open.org/files/BSD-3-Clause.txt) designated for this particular repository (BSD-3-Clause License), and the requirement for an [Individual Contributor License Agreement](https://www.oasis-open.org/resources/open-repositories/cla/individual-cla). Please see the repository [README](https://github.com/oasis-open/cti-stix-validator/blob/master/README.md) document for other details.
 
+## <a id="distinctRules">Governance Distinct from OASIS TC Process</a>
 
-<div>
-<h2><a id="distinctRules">Governance Distinct from OASIS TC Process</a></h2>
-<p>Content accepted as "contributions" to this Open Repository, as <a href="#openRepoContribution">defined</a> below, are distinct from any <a href="https://www.oasis-open.org/policies-guidelines/ipr#contributions">Contributions</a> made to the associated <a href="https://www.oasis-open.org/committees/cti/">OASIS Cyber Threat Intelligence (CTI) TC</a> itself.  Participation in the associated Technical Committee is governed by the <a href="https://www.oasis-open.org/policies-guidelines/bylaws">OASIS Bylaws</a>, <a href="https://www.oasis-open.org/policies-guidelines/tc-process">OASIS TC Process</a>, <a href="https://www.oasis-open.org/policies-guidelines/ipr">IPR Policy</a>, and related <a href="https://www.oasis-open.org/policies-guidelines/">policies</a>.  This Open Repository is not subject to the OASIS TC-related policies.  Open Repository governance is defined by separate <a href="https://www.oasis-open.org/policies-guidelines/open-repositories">participation and contribution guidelines</a> as referenced in the <a href="https://www.oasis-open.org/resources/open-repositories/">OASIS Open Repositories Overview</a>.</p>
-</div>
+Content accepted as "contributions" to this Open Repository, as [defined](#openRepoContribution) below, are distinct from any [Contributions](https://www.oasis-open.org/policies-guidelines/ipr#contributions) made to the associated [OASIS Cyber Threat Intelligence (CTI) TC](https://www.oasis-open.org/committees/cti/) itself. Participation in the associated Technical Committee is governed by the [OASIS Bylaws](https://www.oasis-open.org/policies-guidelines/bylaws), [OASIS TC Process](https://www.oasis-open.org/policies-guidelines/tc-process), [IPR Policy](https://www.oasis-open.org/policies-guidelines/ipr), and related [policies](https://www.oasis-open.org/policies-guidelines/). This Open Repository is not subject to the OASIS TC-related policies. Open Repository governance is defined by separate [participation and contribution guidelines](https://www.oasis-open.org/policies-guidelines/open-repositories) as referenced in the [OASIS Open Repositories Overview](https://www.oasis-open.org/resources/open-repositories/).
 
-<div>
-<h2><a id="distinctLicenses">Licensing Distinct from OASIS IPR Policy</a></h2>
-<p>Because different licenses apply to the OASIS TC's specification work, and this Open Repository, there is no guarantee that the licensure of specific repository material will be compatible with licensing requirements of an implementation of a TC's specification.  Please refer to the <a href="https://github.com/oasis-open/cti-stix-validator/blob/master/LICENSE">LICENSE file</a> for the terms of this material, and to the OASIS IPR Policy for <a href="https://www.oasis-open.org/policies-guidelines/ipr#Non-Assertion-Mode">the terms applicable to the TC's specifications</a>, including any applicable <a href="https://www.oasis-open.org/committees/cti/ipr.php">declarations</a>.</p>
-</div>
+## <a id="distinctLicenses">Licensing Distinct from OASIS IPR Policy</a>
 
-<div>
-<h2><a id="contributionDefined">Contributions Subject to Individual CLA</a></h2>
+Because different licenses apply to the OASIS TC's specification work, and this Open Repository, there is no guarantee that the licensure of specific repository material will be compatible with licensing requirements of an implementation of a TC's specification. Please refer to the [LICENSE file](https://github.com/oasis-open/cti-stix-validator/blob/master/LICENSE) for the terms of this material, and to the OASIS IPR Policy for [the terms applicable to the TC's specifications](https://www.oasis-open.org/policies-guidelines/ipr#Non-Assertion-Mode), including any applicable [declarations](https://www.oasis-open.org/committees/cti/ipr.php).
 
-<p>Formally, <a id="openRepoContribution">"contribution"</a> to this Open Repository refers to content merged into the "Code" repository (repository changes represented by code <a href="https://github.com/oasis-open/cti-stix-validator/commits/master">commits</a>), following the GitHub definition of <i><a href="https://help.github.com/articles/github-glossary/#contributor">contributor</a></i>: "someone who has contributed to a project by having a pull request merged but does not have collaborator [<i>i.e.</i>, direct write] access."  Anyone who signs the Open Repository <a href="https://www.oasis-open.org/resources/open-repositories/cla/individual-cla">Individual Contributor License Agreement (CLA)</a>, signifying agreement with the licensing requirement, may contribute substantive content &mdash; subject to evaluation of a GitHub pull request.  The main web page for this repository, as with any GitHub public repository, displays a link to a document listing contributions to the repository's default branch (filtered by Commits, Additions, and Deletions).</p>
+## <a id="contributionDefined">Contributions Subject to Individual CLA</a>
 
-<p>This Open Repository, as with GitHub public repositories generally, also accepts public feedback from any GitHub user.  Public feedback includes opening issues, authoring and editing comments, participating in conversations, making wiki edits, creating repository stars, and making suggestions via pull requests.  Such feedback does not constitute an OASIS Open Repository <a href="#openRepoContribution">contribution</a>.   Some details are presented under "Read permissions" in the table of <a href="https://help.github.com/articles/repository-permission-levels-for-an-organization/">permission levels</a> for a GitHub organization.  Technical content intended as a substantive contribution (repository "Code") to an Open Repository is subject to evaluation, and requires a signed Individual CLA.</p>
+Formally, <a id="openRepoContribution">"contribution"</a> to this Open Repository refers to content merged into the "Code" repository (repository changes represented by code [commits](https://github.com/oasis-open/cti-stix-validator/commits/master)), following the GitHub definition of _[contributor](https://help.github.com/articles/github-glossary/#contributor)_: "someone who has contributed to a project by having a pull request merged but does not have collaborator [_i.e._, direct write] access." Anyone who signs the Open Repository [Individual Contributor License Agreement (CLA)](https://www.oasis-open.org/resources/open-repositories/cla/individual-cla), signifying agreement with the licensing requirement, may contribute substantive content — subject to evaluation of a GitHub pull request. The main web page for this repository, as with any GitHub public repository, displays a link to a document listing contributions to the repository's default branch (filtered by Commits, Additions, and Deletions).
 
+This Open Repository, as with GitHub public repositories generally, also accepts public feedback from any GitHub user. Public feedback includes opening issues, authoring and editing comments, participating in conversations, making wiki edits, creating repository stars, and making suggestions via pull requests. Such feedback does not constitute an OASIS Open Repository [contribution](#openRepoContribution). Some details are presented under "Read permissions" in the table of [permission levels](https://help.github.com/articles/repository-permission-levels-for-an-organization/) for a GitHub organization. Technical content intended as a substantive contribution (repository "Code") to an Open Repository is subject to evaluation, and requires a signed Individual CLA.
 
-</div>
+## <a id="fork-and-pull-model">Fork-and-Pull Collaboration Model</a>
 
-<div>
-<h2><a id="fork-and-pull-model">Fork-and-Pull Collaboration Model</a></h2>
+OASIS Open Repositories use the familiar [fork-and-pull](https://help.github.com/articles/using-pull-requests/#fork--pull) collaboration model supported by GitHub and other distributed version-control systems. Any GitHub user wishing to contribute should [fork](https://help.github.com/articles/github-glossary/#fork) the repository, make additions or other modifications, and then submit a pull request. GitHub pull requests should be accompanied by supporting [comments](https://help.github.com/articles/commenting-on-the-diff-of-a-pull-request/) and/or [issues](https://help.github.com/articles/about-issues/). Community conversations about pull requests, supported by GitHub [notifications](https://help.github.com/articles/about-notifications/), will provide the basis for a consensus determination to merge, modify, close, or take other action, as communicated by the repository [Maintainers](https://www.oasis-open.org/resources/open-repositories/maintainers-guide).
 
-<p>OASIS Open Repositories use the familiar <a href="https://help.github.com/articles/using-pull-requests/#fork--pull">fork-and-pull</a> collaboration model supported by GitHub and other distributed version-control systems.  Any GitHub user wishing to contribute should <a href="https://help.github.com/articles/github-glossary/#fork">fork</a> the repository, make additions or other modifications, and then submit a pull request.  GitHub pull requests should be accompanied by supporting <a href="https://help.github.com/articles/commenting-on-the-diff-of-a-pull-request/">comments</a> and/or <a href="https://help.github.com/articles/about-issues/">issues</a>. Community conversations about pull requests, supported by GitHub <a href="https://help.github.com/articles/about-notifications/">notifications</a>, will provide the basis for a consensus determination to merge, modify, close, or take other action, as communicated by the repository <a href="https://www.oasis-open.org/resources/open-repositories/maintainers-guide">Maintainers</a>.</p>
-</div>
+## <a id="feedback">Feedback</a>
 
-<div>
-<h2><a id="feedback">Feedback</a></h2>
-
-<p>Questions or comments about this Open Repository's activities should be composed as GitHub issues or comments. If use of an issue/comment is not possible or appropriate, questions may be directed by email to the <a href="https://github.com/oasis-open/cti-stix-validator/blob/master/README.md#maintainers">repository Maintainer(s)</a>.  Please send general questions about Open Repository participation to OASIS Staff at <a href="mailto:repository-admin@oasis-open.org">repository-admin@oasis-open.org</a> and any specific CLA-related questions to <a href="mailto:repository-cla@oasis-open.org">repository-cla@oasis-open.org</a>.</p>
-
-</div></div>
+Questions or comments about this Open Repository's activities should be composed as GitHub issues or comments. If use of an issue/comment is not possible or appropriate, questions may be directed by email to the [repository Maintainer(s)](https://github.com/oasis-open/cti-stix-validator/blob/master/README.md#maintainers). Please send general questions about Open Repository participation to OASIS Staff at [repository-admin@oasis-open.org](mailto:repository-admin@oasis-open.org) and any specific CLA-related questions to [repository-cla@oasis-open.org](mailto:repository-cla@oasis-open.org).
diff --git a/README.rst b/README.rst
index 7a93b57..7d1db28 100644
--- a/README.rst
+++ b/README.rst
@@ -1,10 +1,11 @@
+======
 README
 ======
 
 .. _readme-general:
 
 `OASIS Open Repository: cti-stix-validator`
--------------------------------------------
+===========================================
 This GitHub public repository ( `https://github.com/oasis-open/cti-stix-validator <https://github.com/oasis-open/cti-stix-validator>`_ ) was created at the request of the `OASIS Cyber Threat Intelligence (CTI) TC <https://www.oasis-open.org/committees/cti/>`_ as an `OASIS Open Repository <https://www.oasis-open.org/resources/open-repositories/>`_ to support development of open source resources related to Technical Committee work.
 
 While this Open Repository remains associated with the sponsor TC, its development priorities, leadership, intellectual property terms, participation rules, and other matters of governance are `separate and distinct <https://github.com/oasis-open/cti-stix-validator/blob/master/CONTRIBUTING.md#governance-distinct-from-oasis-tc-process>`_ from the OASIS TC Process and related policies.
@@ -16,7 +17,7 @@ As documented in `"Public Participation Invited" <https://github.com/oasis-open/
 .. _purposeStatement:
 
 `Statement of Purpose`
-----------------------
+======================
 Statement of Purpose for this OASIS Open Repository (cti-stix-validator) as `proposed <https://lists.oasis-open.org/archives/cti/201609/msg00001.html>`_ and `approved <https://www.oasis-open.org/committees/ballot.php?id=2971>`_ [`bis <https://issues.oasis-open.org/browse/TCADMIN-2434>`_] by the TC:
 
 The STIX validator checks that STIX JSON content conforms to the requirements specified in the STIX 2.0 specification. In addition to checking conformance with the JSON schemas, the validator checks conformance with requirements that cannot be specified in JSON schema, as well as with established "best practices." This validator is non-normative; in cases of conflict with the STIX 2.0 specification, the specification takes precedence.
@@ -24,8 +25,8 @@ The STIX validator checks that STIX JSON content conforms to the requirements sp
 .. _purposeClarifications:
 
 `Additions to Statement of Purpose`
------------------------------------
-Some requirements in the STIX 2.0 specification are mandatory; others are merely recommended. The validator checks documents against the mandatory requirements using JSON schemas. Some of the mandatory requirements cannot be implemented in JSON Schema, however, so the validator uses Python functions to check these. The recommended requirements are all checked by Python functions, and options can be set to ignore all or some of these recommended "best practices." 
+===================================
+The STIX 2.0 specification contains two types of requirements: mandatory "MUST" requirements, and recommended "SHOULD" best practice requirements. The validator checks documents against the "MUST" requirements using JSON schemas. Some of these mandatory requirements cannot be implemented in JSON Schema, however, so the validator uses Python functions to check them. The "SHOULD" requirements are all checked by Python functions, and options may be used to ignore some or all of these recommended "best practices."
 
 The only exception to this is the mandatory requirement that an object's 'type' be one of those defined by a STIX Object in the specification. This rules out custom objects, so this check was made optional.
 
@@ -34,7 +35,7 @@ The validator also color-codes its output to make it easier to tell at a glance
 .. _install:
 
 `Installation`
-,,,,,,,,,,,,,,
+--------------
 
 The easiest way to install the STIX validator is with pip:
 
@@ -42,7 +43,7 @@ The easiest way to install the STIX validator is with pip:
 
   $ pip install git+https://github.com/oasis-open/cti-stix-validator.git
 
-Note that if you clone or download the repository and install it that way instead, you will need to set up the submodules before you install it:
+Note that if you instead install it by cloning or downloading the repository, you will need to set up the submodules before you install it:
 
 ::
 
@@ -54,9 +55,10 @@ Note that if you clone or download the repository and install it that way instea
 .. _usage:
 
 `Usage`
-,,,,,,,
+-------
 
-**As A Script**
+As A Script
+~~~~~~~~~~~
 
 The validator comes with a bundled script which you can use to validate a JSON file containing STIX content:
 
@@ -64,7 +66,8 @@ The validator comes with a bundled script which you can use to validate a JSON f
 
   $ stix2_validator <stix_file.json>
 
-**As A Library**
+As A Library
+~~~~~~~~~~~~
 
 You can also use this library to integrate STIX validation into your own tools. You can validate a JSON file:
 
@@ -86,10 +89,104 @@ You can also validate a JSON string, and check if the input passed validation:
   if results.is_valid:
       print_results(results)
 
+You can pass in a ValidationOptions object if you want behavior other than the default:
+
+.. code:: python
+
+  from stix2validator import ValidationOptions
+
+  options = ValidationOptions(strict=True)
+  results = validate_string(stix_json_string, options)
+
+.. _options:
+
+Checking Best Practices
+~~~~~~~~~~~~~~~~~~~~~~~
+
+The validator will always validate input against all of the mandatory "MUST" requirements from the spec. By default it will issue warnings if the input fails any of the "SHOULD" recommendations, but validation will still pass. To turn these "best practice" warnings into errors and cause validation to fail, use the :code:`--strict` option with the command-line script, or create a ValidationOptions object with :code:`strict=True` when using the library.
+
+You cannot select which of the "MUST" requirement checks will be performed; all of them will always be performed. However, you may select which of the "SHOULD" checks to perform. Use the codes from the table below to enable or disable these checks. For example, to disable the checks for the report label and tool label vocabularies, use :code:`--disable 218,222` or :code:`disabled="218,222"`. All the other checks will still be performed. Conversely, to only check that custom property names adhere to the recommended format but not run any of the other "best practice" checks, use :code:`--enable 103` or :code:`enabled="103"`.
+
+Enabling supersedes disabling. Simultaneously enabling and disabling the same check will result in the validator performing that check.
+
+**Recommended Best Practice Check Codes**
+
++--------+-----------------------------+----------------------------------------+
+|**Code**|**Name**                     |**Ensures...**                          |
++--------+-----------------------------+----------------------------------------+
+|   1    | format-checks               | all 1xx checks are run                 |
++--------+-----------------------------+----------------------------------------+
+|  101   | custom-object-prefix        | custom object type names follow the    |
+|        |                             | correct format                         |
++--------+-----------------------------+----------------------------------------+
+|  102   | custom-object-prefix-lax    | same as 101 but more lenient; no       |
+|        |                             | source identifier needed in prefix     |
++--------+-----------------------------+----------------------------------------+
+|  103   | custom-property-prefix      | custom object property names follow    |
+|        |                             | the correct format                     |
++--------+-----------------------------+----------------------------------------+
+|  104   | custom-property-prefix-lax  | same as 103 but more lenient; no       |
+|        |                             | source identifier needed in prefix     |
++--------+-----------------------------+----------------------------------------+
+|  111   | open-vocab-format           | values of open vocabularies follow the |
+|        |                             | correct format                         |
++--------+-----------------------------+----------------------------------------+
+|  121   | kill-chain-names            | kill-chain-phase name and phase follow |
+|        |                             | the correct format                     |
+|        |                             |                                        |
++--------+-----------------------------+----------------------------------------+
+|   2    | approved-values             | all 2xx checks are run                 |
++--------+-----------------------------+----------------------------------------+
+|  210   | all-vocabs                  | all of the following open vocabulary   |
+|        |                             | checks are run                         |
++--------+-----------------------------+----------------------------------------+
+|  211   | attack-motivation           | certain property values are from the   |
+|        |                             | attack_motivation vocabulary           |
++--------+-----------------------------+----------------------------------------+
+|  212   | attack-resource-level       | certain property values are from the   |
+|        |                             | attack_resource_level vocabulary       |
++--------+-----------------------------+----------------------------------------+
+|  213   | identity-class              | certain property values are from the   |
+|        |                             | identity_class vocabulary              |
++--------+-----------------------------+----------------------------------------+
+|  214   | indicator-label             | certain property values are from the   |
+|        |                             | indicator_label vocabulary             |
++--------+-----------------------------+----------------------------------------+
+|  215   | industry-sector             | certain property values are from the   |
+|        |                             | industry_sector vocabulary             |
++--------+-----------------------------+----------------------------------------+
+|  216   | malware-label               | certain property values are from the   |
+|        |                             | malware_label vocabulary               |
++--------+-----------------------------+----------------------------------------+
+|  217   | pattern-lang                | certain property values are from the   |
+|        |                             | pattern_lang vocabulary                |
++--------+-----------------------------+----------------------------------------+
+|  218   | report-label                | certain property values are from the   |
+|        |                             | report_label vocabulary                |
++--------+-----------------------------+----------------------------------------+
+|  219   | threat-actor-label          | certain property values are from the   |
+|        |                             | threat_actor_label vocabulary          |
++--------+-----------------------------+----------------------------------------+
+|  220   | threat-actor-role           | certain property values are from the   |
+|        |                             | threat_actor_role vocabulary           |
++--------+-----------------------------+----------------------------------------+
+|  221   | threat-actor-sophistication | certain property values are from the   |
+|        |                             | threat_actor_sophistication vocabulary |
++--------+-----------------------------+----------------------------------------+
+|  222   | tool-label                  | certain property values are from the   |
+|        |                             | tool_label vocabulary                  |
++--------+-----------------------------+----------------------------------------+
+|  229   | marking-definition-type     | marking definitions use a valid        |
+|        |                             | definition_type                        |
++--------+-----------------------------+----------------------------------------+
+|  250   | relationship-types          | relationships are among those defined  |
+|        |                             | in the specification                   |
++--------+-----------------------------+----------------------------------------+
+
 .. _maintainers:
 
 `Maintainers`
--------------
+=============
 Open Repository `Maintainers <https://www.oasis-open.org/resources/open-repositories/maintainers-guide>`__ are responsible for oversight of this project's community development activities, including evaluation of GitHub `pull requests <https://github.com/oasis-open/cti-stix-validator/blob/master/CONTRIBUTING.md#fork-and-pull-collaboration-model>`_ and `preserving <https://www.oasis-open.org/policies-guidelines/open-repositories#repositoryManagement>`_ open source principles of openness and fairness. Maintainers are recognized and trusted experts who serve to implement community goals and consensus design preferences.
 
 Initially, the associated TC members have designated one or more persons to serve as Maintainer(s); subsequently, participating community members may select additional or substitute Maintainers, per `consensus agreements <https://www.oasis-open.org/resources/open-repositories/maintainers-guide#additionalMaintainers>`_.
@@ -106,7 +203,7 @@ Initially, the associated TC members have designated one or more persons to serv
 .. _aboutOpenRepos:
 
 `About OASIS Open Repositories`
--------------------------------
+===============================
 *  `Open Repositories: Overview and Resources <https://www.oasis-open.org/resources/open-repositories/>`_
 *  `Frequently Asked Questions <https://www.oasis-open.org/resources/open-repositories/faq>`_
 *  `Open Source Licenses <https://www.oasis-open.org/resources/open-repositories/licenses>`_
@@ -116,5 +213,5 @@ Initially, the associated TC members have designated one or more persons to serv
 .. _feedback:
 
 `Feedback`
-----------
+==========
 Questions or comments about this Open Repository's activities should be composed as GitHub issues or comments. If use of an issue/comment is not possible or appropriate, questions may be directed by email to the Maintainer(s) `listed above <#currentMaintainers>`_. Please send general questions about Open Repository participation to OASIS Staff at `repository-admin@oasis-open.org <mailto:repository-admin@oasis-open.org>`_ and any specific CLA-related questions to `repository-cla@oasis-open.org <mailto:repository-cla@oasis-open.org>`_.
diff --git a/stix2validator/__init__.py b/stix2validator/__init__.py
index 3a039f7..3fafd02 100644
--- a/stix2validator/__init__.py
+++ b/stix2validator/__init__.py
@@ -18,6 +18,13 @@ from .validators import ValidationOptions, CustomDraft4Validator
 from .output import print_results # Expose it to the stix2validator namespace
 
 
+class NoJSONFileFoundError(OSError):
+    """Represent a problem finding the input JSON file(s).
+
+    """
+    pass
+
+
 class ValidationError(Exception):
     """Base Exception for all validator-specific exceptions. This can be used
     directly as a generic Exception.
@@ -26,7 +33,7 @@ class ValidationError(Exception):
 
 
 class SchemaInvalidError(ValidationError):
-    """Represents an error with the JSON Schema file itself.
+    """Represent an error with the JSON Schema file itself.
 
     """
     def __init__(self, msg=None, results=None):
@@ -39,7 +46,7 @@ class SchemaInvalidError(ValidationError):
 
 @python_2_unicode_compatible
 class SchemaError(ValidationError):
-    """Represents a JSON Schema validation error.
+    """Represent a JSON Schema validation error.
 
     Args:
         error: An error returned from JSON Schema validation.
@@ -66,9 +73,8 @@ class SchemaError(ValidationError):
 
 
 def pretty_error(error, verbose=False):
-    """Returns an error message that is easier to read and more useful.
+    """Return an error message that is easier to read and more useful.
     """
-    import logging
     error_loc = ''
     try:
         error_loc = error.instance['id'] + ': '
@@ -169,7 +175,7 @@ class BaseResults(object):
         self._is_valid = bool(value)
 
     def as_dict(self):
-        """Returns a dictionary representation of this class.
+        """Return a dictionary representation of this class.
 
         Keys:
             ``'result'``: The validation result. Values will be ``True`` or
@@ -192,6 +198,7 @@ class ValidationResults(BaseResults):
         errors: A list of exception strings reported by the JSON validation
             engine.
         fatal: A fatal error.
+        warnings: A list of warning strings reported by our custom validators.
         fn: The filename/path for the file that was validated; None if a string
             was validated.
 
@@ -200,10 +207,12 @@ class ValidationResults(BaseResults):
             otherwise.
 
     """
-    def __init__(self, is_valid=False, errors=None, fatal=None, fn=None):
+    def __init__(self, is_valid=False, errors=None, fatal=None, warnings=None,
+                 fn=None):
         super(ValidationResults, self).__init__(is_valid)
         self.errors = errors
         self.fatal = fatal
+        self.warnings = warnings
         self.fn = fn
 
     @property
@@ -273,7 +282,7 @@ def is_json(fn):
 
 
 def list_json_files(directory, recursive=False):
-    """Returns a list of file paths for JSON files within `directory`.
+    """Return a list of file paths for JSON files within `directory`.
 
     Args:
         directory: A path to a directory.
@@ -300,7 +309,7 @@ def list_json_files(directory, recursive=False):
 
 
 def get_json_files(files, recursive=False):
-    """Returns a list of files to validate from `files`. If a member of `files`
+    """Return a list of files to validate from `files`. If a member of `files`
     is a directory, its children with a ``.json`` extension will be added to
     the return value.
 
@@ -327,12 +336,14 @@ def get_json_files(files, recursive=False):
         else:
             continue
 
+    if not json_files:
+        raise NoJSONFileFoundError("No JSON files found!")
     return json_files
 
 
 
 def run_validation(options):
-    """Validates files based on command line options.
+    """Validate files based on command line options.
 
     Args:
         options: An instance of ``ValidationOptions`` containing options for
@@ -340,7 +351,10 @@ def run_validation(options):
 
     """
     # The JSON files to validate
-    files = get_json_files(options.files, options.recursive)
+    try:
+        files = get_json_files(options.files, options.recursive)
+    except NoJSONFileFoundError as e:
+        output.error(e.message)
 
     results = {}
     for fn in files:
@@ -350,7 +364,7 @@ def run_validation(options):
 
 
 def validate_file(fn, options=None):
-    """Validates the input document `fn` according to the options passed in.
+    """Validate the input document `fn` according to the options passed in.
 
     If any exceptions are raised during validation, no further validation
     will take place.
@@ -393,7 +407,7 @@ def validate_file(fn, options=None):
 
 
 def validate_string(string, options=None):
-    """Validates the input `string` according to the options passed in.
+    """Validate the input `string` according to the options passed in.
 
     If any exceptions are raised during validation, no further validation
     will take place.
@@ -428,7 +442,7 @@ def validate_string(string, options=None):
 
 
 def load_validator(schema_path, schema, options):
-    """Creates a JSON schema validator for the given schema.
+    """Create a JSON schema validator for the given schema.
 
     Args:
         schema_path: The filename of the JSON schema.
@@ -451,8 +465,8 @@ def load_validator(schema_path, schema, options):
 
 
 def find_schema(schema_dir, obj_type):
-    """Searches the `schema_dir` directory for a schema called `obj_type`.json.
-    Returns the file path of the first match it finds.
+    """Search the `schema_dir` directory for a schema called `obj_type`.json.
+    Return the file path of the first match it finds.
     """
     for root, dirnames, filenames in os.walk(schema_dir):
         for filename in fnmatch.filter(filenames, obj_type + '.json'):
@@ -460,7 +474,7 @@ def find_schema(schema_dir, obj_type):
 
 
 def load_schema(schema_path):
-    """Loads the JSON schema at the given path as a Python object.
+    """Load the JSON schema at the given path as a Python object.
 
     Args:
         schema_path: A filename for a JSON schema.
@@ -480,8 +494,8 @@ def load_schema(schema_path):
 
 
 def schema_validate(instance, options):
-    """Performs STIX JSON Schema validation against the input JSON.
-    Finds the correct schema by looking at the 'type' property of the
+    """Perform STIX JSON Schema validation against the input JSON.
+    Find the correct schema by looking at the 'type' property of the
     `instance` JSON object.
 
     Args:
@@ -523,13 +537,21 @@ def schema_validate(instance, options):
     try:
         some_errors = validator.iter_errors(instance)
         more_errors = validator.iter_errors_more(instance)
-        chained_errors = chain(some_errors, more_errors)
+        warnings = validator.iter_errors_more(instance, False)
+
+        if options.strict:
+            chained_errors = chain(some_errors, more_errors, warnings)
+            warnings = None
+        else:
+            chained_errors = chain(some_errors, more_errors)
+            warnings = [pretty_error(x, options.verbose) for x in warnings]
+
         errors = sorted(chained_errors, key=lambda e: e.path)
     except schema_exceptions.RefResolutionError:
         raise SchemaInvalidError('Invalid JSON schema: a JSON reference '
                                  'failed to resolve')
 
-    if len(errors) == 0:
+    if not errors and not warnings:
         return ValidationResults(True)
 
     # Prepare the list of errors
@@ -538,4 +560,10 @@ def schema_validate(instance, options):
         msg = pretty_error(error, options.verbose)
         error_list.append(SchemaError(msg))
 
-    return ValidationResults(False, error_list)
+    if error_list:
+        valid = False
+    else:
+        valid = True
+
+    return ValidationResults(is_valid=valid, errors=error_list,
+                             warnings=warnings)
diff --git a/stix2validator/output.py b/stix2validator/output.py
index d2d0db6..0097737 100644
--- a/stix2validator/output.py
+++ b/stix2validator/output.py
@@ -1,10 +1,11 @@
 import sys
 from colorama import init, Fore, Style
-from six import iteritems, text_type
+from six import iteritems
 from . import codes
 
 init(autoreset=True)
 _GREEN = Fore.GREEN
+_YELLOW = Fore.YELLOW
 _RED = Fore.RED + Style.BRIGHT
 _VERBOSE = False
 
@@ -20,7 +21,7 @@ def set_level(verbose_output=False):
 
 
 def error(msg, status=codes.EXIT_FAILURE):
-    """Prints a message to the stderr prepended by '[!]' and calls
+    """Prints a message to the stderr prepended by '[X]' and calls
     ```sys.exit(status)``.
 
     Args:
@@ -28,7 +29,7 @@ def error(msg, status=codes.EXIT_FAILURE):
         status: The exit status code. Defaults to ``EXIT_FAILURE`` (1).
 
     """
-    sys.stderr.write("[!] %s\n" % str(msg))
+    sys.stderr.write(_RED + "[X] %s\n" % str(msg))
     sys.exit(status)
 
 
@@ -78,29 +79,32 @@ def print_level(fmt, level, *args):
 def print_fatal_results(results, level=0):
     """Prints fatal errors that occurred during validation runs.
     """
-    print_level(_RED + "[!] Fatal Error: %s", level, results.error)
+    print_level(_RED + "[X] Fatal Error: %s", level, results.error)
 
 
 def print_schema_results(results, level=0):
-    """Prints JSON Schema validation results to stdout.
+    """Prints JSON Schema validation errors to stdout.
 
     Args:
         results: An instance of ValidationResults.
         level: The level at which to print the results.
 
     """
-    marker = _GREEN + "[+]" if results.is_valid else _RED + "[!]"
-    print_level("%s JSON Schema: %s", level, marker, results.is_valid)
+    for error in results.errors:
+        print_level(_RED + "[X] %s", level + 1, error)
 
-    if results.is_valid:
-        return
 
-    for error in results.errors:
-        print_level(_RED + "[!] %s", level + 1, error)
+def print_warning_results(results, level=0):
+    """Prints warning messages found during validation.
+    """
+    marker = _YELLOW + "[!] "
+
+    for warning in results.warnings:
+        print_level(marker + "Warning: %s", level + 1, warning)
 
 
 def print_results(results):
-    """Prints `results` to stdout.
+    """Prints `results` (the results of validation) to stdout.
 
     Args:
         results: A dictionary of ValidationResults instances. The key is the
@@ -114,9 +118,19 @@ def print_results(results):
     level = 0
     for fn, result in sorted(iteritems(results)):
         print("=" * 80)
-        print_level("[-] Results: %s", level, fn)
-
-        if result.errors is not None:
+        print_level("[-] Results for: %s", level, fn)
+
+        if result.is_valid:
+            marker = _GREEN + "[+]"
+            verdict = "Valid"
+        else:
+            marker = _RED + "[X]"
+            verdict = "Invalid"
+        print_level("%s STIX JSON: %s", level, marker, verdict)
+
+        if result.warnings:
+            print_warning_results(result, level)
+        if result.errors:
             print_schema_results(result, level)
-        if result.fatal is not None:
+        if result.fatal:
             print_fatal_results(result.fatal, level)
diff --git a/stix2validator/scripts/stix2_validator.py b/stix2validator/scripts/stix2_validator.py
index 1ee094a..e69f35c 100644
--- a/stix2validator/scripts/stix2_validator.py
+++ b/stix2validator/scripts/stix2_validator.py
@@ -138,10 +138,11 @@ def _get_arg_parser(is_script=True):
         "-d",
         "--disable",
         "--ignore",
-        dest="ignored",
+        dest="disabled",
         default="",
         help="A comma-separated list of recommended best practice checks to "
-            "skip. \n\nExample: --ignore 212,220"
+            "skip. By default, no checks are disabled. \n\n"
+            "Example: --disable 212,220"
     )
 
     parser.add_argument(
@@ -152,18 +153,16 @@ def _get_arg_parser(is_script=True):
         default="",
         help="A comma-separated list of recommended best practice checks to "
             "enable. If the --disable option is not used, no other checks will"
-            " be run. \n\nExample: --enable 250"
+            " be run. By default, all checks are enabled.\n\n"
+            "Example: --enable 250"
     )
 
     parser.add_argument(
-        "-l",
-        "--lax",
-        dest="lax",
+        "--strict",
+        dest="strict",
         action="store_true",
         default=False,
-        help="Ignore all recommended best practices and only check mandatory "
-             "requirements. This option takes precedent over --enable or "
-             "--disable. Equivalent to: --disable all"
+        help="Treat warnings as errors and fail validation if any are found."
     )
 
     parser.add_argument(
diff --git a/stix2validator/validators.py b/stix2validator/validators.py
index 4472418..d77dfed 100644
--- a/stix2validator/validators.py
+++ b/stix2validator/validators.py
@@ -31,25 +31,25 @@ class ValidationOptions(object):
             validated.
         recursive: Recursively descend into input directories.
         schema_dir: A user-defined schema directory to validate against.
-        lax: Specifies that only mandatory requirements, not ones which are
-            merely recommended, should be checked.
-        lax_prefix: Specifies that less strict requirements for custom object
-            and property names should be used.
+        disabled: List of "SHOULD" checks that will be skipped.
+        enabled: List of "SHOULD" checks that will be performed.
+        strict: Specifies that recommended requirements should produce errors
+            instead of mere warnings.
         strict_types: Specifies that no custom object types be used, only
             those detailed in the STIX specification.
 
     """
     def __init__(self, cmd_args=None, verbose=False, files=None,
-                 recursive=False, schema_dir=None, ignored="",
-                 enabled="", lax=False, strict_types=False):
+                 recursive=False, schema_dir=None, disabled="",
+                 enabled="", strict=False, strict_types=False):
         if cmd_args is not None:
             self.verbose = cmd_args.verbose
             self.files = cmd_args.files
             self.recursive = cmd_args.recursive
             self.schema_dir = cmd_args.schema_dir
-            self.ignored = cmd_args.ignored
+            self.disabled = cmd_args.disabled
             self.enabled = cmd_args.enabled
-            self.lax = cmd_args.lax
+            self.strict = cmd_args.strict
             self.strict_types = cmd_args.strict_types
         else:
             # input options
@@ -59,9 +59,9 @@ class ValidationOptions(object):
 
             # output options
             self.verbose = verbose
-            self.lax = lax
+            self.strict = strict
             self.strict_types = strict_types
-            self.ignored = ignored
+            self.disabled = disabled
             self.enabled = enabled
 
         # If no schema directory given, use default bundled with this package
@@ -71,10 +71,10 @@ class ValidationOptions(object):
 
         # Convert string of comma-separated checks to a list,
         # and convert check code numbers to names
-        if self.ignored:
-            self.ignored = self.ignored.split(",")
-            self.ignored = [CHECK_CODES[x] if x in CHECK_CODES else x
-                                   for x in self.ignored]
+        if self.disabled:
+            self.disabled = self.disabled.split(",")
+            self.disabled = [CHECK_CODES[x] if x in CHECK_CODES else x
+                                   for x in self.disabled]
         if self.enabled:
             self.enabled = self.enabled.split(",")
             self.enabled = [CHECK_CODES[x] if x in CHECK_CODES else x
@@ -536,6 +536,7 @@ class CustomDraft4Validator(Draft4Validator):
         super(CustomDraft4Validator, self).__init__(schema, types, resolver,
                                                     format_checker)
         self.validator_list = self.list_validators(options)
+        self.shoulds_list = self.list_shoulds(options)
 
     def list_validators(self, options):
         """Construct the list of validators to be run by this validator.
@@ -550,78 +551,77 @@ class CustomDraft4Validator(Draft4Validator):
         if options.strict_types:
             validator_list.append(types_strict)
 
-        # --lax
-        # If only checking MUST requirements, the list is complete
-        if options.lax:
-            return validator_list
+        return validator_list
 
+    def list_shoulds(self, options):
+        validator_list = []
         # Default: enable all
-        if not options.ignored and not options.enabled:
+        if not options.disabled and not options.enabled:
             validator_list.extend(CHECKS['all'])
             return validator_list
 
         # --disable
-        # Add SHOULD requirements to the list unless ignored
-        if options.ignored:
-            if 'all' not in options.ignored:
-                if 'format-checks' not in options.ignored:
-                    if ('custom-object-prefix' not in options.ignored and
-                            'custom-object-prefix-lax' not in options.ignored):
+        # Add SHOULD requirements to the list unless disabled
+        if options.disabled:
+            if 'all' not in options.disabled:
+                if 'format-checks' not in options.disabled:
+                    if ('custom-object-prefix' not in options.disabled and
+                            'custom-object-prefix-lax' not in options.disabled):
                         validator_list.append(CHECKS['custom-object-prefix'])
-                    elif 'custom-object-prefix' not in options.ignored:
+                    elif 'custom-object-prefix' not in options.disabled:
                         validator_list.append(CHECKS['custom-object-prefix'])
-                    elif 'custom-object-prefix-lax' not in options.ignored:
+                    elif 'custom-object-prefix-lax' not in options.disabled:
                         validator_list.append(CHECKS['custom-object-prefix-lax'])
-                    if ('custom-property-prefix' not in options.ignored and
-                            'custom-property-prefix-lax' not in options.ignored):
+                    if ('custom-property-prefix' not in options.disabled and
+                            'custom-property-prefix-lax' not in options.disabled):
                         validator_list.append(CHECKS['custom-property-prefix'])
-                    elif 'custom-property-prefix' not in options.ignored:
+                    elif 'custom-property-prefix' not in options.disabled:
                         validator_list.append(CHECKS['custom-property-prefix'])
-                    elif 'custom-property-prefix-lax' not in options.ignored:
+                    elif 'custom-property-prefix-lax' not in options.disabled:
                         validator_list.append(CHECKS['custom-property-prefix-lax'])
-                    if 'open-vocab-format' not in options.ignored:
+                    if 'open-vocab-format' not in options.disabled:
                         validator_list.append(CHECKS['open-vocab-format'])
-                    if 'kill-chain-names' not in options.ignored:
+                    if 'kill-chain-names' not in options.disabled:
                         validator_list.append(CHECKS['kill-chain-names'])
 
-                if 'approved-values' not in options.ignored:
-                    if 'all-vocabs' not in options.ignored:
-                        if 'attack-motivation' not in options.ignored:
+                if 'approved-values' not in options.disabled:
+                    if 'all-vocabs' not in options.disabled:
+                        if 'attack-motivation' not in options.disabled:
                             validator_list.append(CHECKS['attack-motivation'])
-                        if 'attack-resource-level' not in options.ignored:
+                        if 'attack-resource-level' not in options.disabled:
                             validator_list.append(CHECKS['attack-resource-level'])
-                        if 'identity-class' not in options.ignored:
+                        if 'identity-class' not in options.disabled:
                             validator_list.append(CHECKS['identity-class'])
-                        if 'indicator-label' not in options.ignored:
+                        if 'indicator-label' not in options.disabled:
                             validator_list.append(CHECKS['indicator-label'])
-                        if 'industry-sector' not in options.ignored:
+                        if 'industry-sector' not in options.disabled:
                             validator_list.append(CHECKS['industry-sector'])
-                        if 'malware-label' not in options.ignored:
+                        if 'malware-label' not in options.disabled:
                             validator_list.append(CHECKS['malware-label'])
-                        if 'pattern-lang' not in options.ignored:
+                        if 'pattern-lang' not in options.disabled:
                             validator_list.append(CHECKS['pattern-lang'])
-                        if 'report-label' not in options.ignored:
+                        if 'report-label' not in options.disabled:
                             validator_list.append(CHECKS['report-label'])
-                        if 'threat-actor-label' not in options.ignored:
+                        if 'threat-actor-label' not in options.disabled:
                             validator_list.append(CHECKS['threat-actor-label'])
-                        if 'threat-actor-role' not in options.ignored:
+                        if 'threat-actor-role' not in options.disabled:
                             validator_list.append(CHECKS['threat-actor-role'])
-                        if 'threat-actor-sophistication' not in options.ignored:
+                        if 'threat-actor-sophistication' not in options.disabled:
                             validator_list.append(CHECKS['threat-actor-sophistication'])
-                        if 'tool-label' not in options.ignored:
+                        if 'tool-label' not in options.disabled:
                             validator_list.append(CHECKS['tool-label'])
-                        if 'marking-definition-type' not in options.ignored:
+                        if 'marking-definition-type' not in options.disabled:
                             validator_list.append(CHECKS['marking-definition-type'])
-                    if 'relationship-types' not in options.ignored:
+                    if 'relationship-types' not in options.disabled:
                         validator_list.append(CHECKS['relationship-types'])
 
         # --enable
         if options.enabled:
             for check in options.enabled:
-                if CHECKS[check] in validator_list:
-                    continue
-
                 try:
+                    if CHECKS[check] in validator_list:
+                        continue
+
                     if type(CHECKS[check]) is list:
                         validator_list.extend(CHECKS[check])
                     else:
@@ -632,19 +632,28 @@ class CustomDraft4Validator(Draft4Validator):
 
         return validator_list
 
-    def iter_errors_more(self, instance, options=None, _schema=None):
+    def iter_errors_more(self, instance, check_musts=True):
         """Perform additional validation not possible merely with JSON schemas.
 
+        Args:
+            instance: The STIX object to be validated.
+            check_musts: If True, this function will check against the
+                additional mandatory "MUST" requirements which cannot be
+                enforced by schemas. If False, this function will check against
+                recommended "SHOULD" best practices instead. This function will
+                never check both; to do so call it twice.
         """
         # Ensure `instance` is a whole STIX object, not just a property of one
         if not (type(instance) is dict and 'id' in instance and 'type' in instance):
             return
 
-        if _schema is None:
-            _schema = self.schema
+        if check_musts:
+            validators = self.validator_list
+        else:
+            validators = self.shoulds_list
 
         # Perform validation
-        for v_function in self.validator_list:
+        for v_function in validators:
             result = v_function(instance)
             if result is not None:
                 yield result
@@ -653,5 +662,5 @@ class CustomDraft4Validator(Draft4Validator):
         for field in instance:
             if type(instance[field]) is list:
                 for obj in instance[field]:
-                    for err in self.iter_errors_more(obj, _schema):
+                    for err in self.iter_errors_more(obj, check_musts):
                         yield err


Test patch:
diff --git a/stix2validator/test/__init__.py b/stix2validator/test/__init__.py
index 2d61701..abae333 100644
--- a/stix2validator/test/__init__.py
+++ b/stix2validator/test/__init__.py
@@ -7,7 +7,7 @@ SCHEMA_DIR = os.path.abspath(os.path.dirname(__file__) + "../../schemas")
 
 
 class ValidatorTest(unittest.TestCase):
-    options = ValidationOptions(schema_dir=SCHEMA_DIR)
+    options = ValidationOptions(schema_dir=SCHEMA_DIR, strict=True)
 
     def check_ignore(self, instance, code):
         """Test that the given instance is valid if the given check is ignored.
@@ -16,7 +16,7 @@ class ValidatorTest(unittest.TestCase):
             instance: The JSON string to be validated.
             error: The numerical code of the check to be ignored.
         """
-        self.assertTrueWithOptions(instance, ignored=code)
+        self.assertTrueWithOptions(instance, disabled=code)
 
     def assertTrueWithOptions(self, instance, **kwargs):
         """Test that the given instance is valid when using the validation
@@ -27,7 +27,11 @@ class ValidatorTest(unittest.TestCase):
             kwargs: Any number of keyword arguments to be passed to the
                     ValidationOptions constructor.
         """
-        options = ValidationOptions(schema_dir=SCHEMA_DIR, **kwargs)
+        if 'strict' in kwargs:
+            options = ValidationOptions(schema_dir=SCHEMA_DIR, **kwargs)
+        else:
+            options = ValidationOptions(schema_dir=SCHEMA_DIR, strict=True,
+                                        **kwargs)
         results = validate_string(instance, options)
         self.assertTrue(results.is_valid)
 
@@ -40,6 +44,10 @@ class ValidatorTest(unittest.TestCase):
             kwargs: Any number of keyword arguments to be passed to the
                     ValidationOptions constructor.
         """
-        options = ValidationOptions(schema_dir=SCHEMA_DIR, **kwargs)
+        if 'strict' in kwargs:
+            options = ValidationOptions(schema_dir=SCHEMA_DIR, **kwargs)
+        else:
+            options = ValidationOptions(schema_dir=SCHEMA_DIR, strict=True,
+                                        **kwargs)
         results = validate_string(instance, options)
         self.assertEqual(results.is_valid, False)
diff --git a/stix2validator/test/malware_tests.py b/stix2validator/test/malware_tests.py
index 8b5a831..90cae2a 100644
--- a/stix2validator/test/malware_tests.py
+++ b/stix2validator/test/malware_tests.py
@@ -39,21 +39,21 @@ class MalwareTestCases(ValidatorTest):
         malware['labels'] += "Ransomware"
         malware = json.dumps(malware)
         self.assertFalseWithOptions(malware,
-                                    ignored='malware-label')
+                                    disabled='malware-label')
 
     def test_open_vocab_format_underscore(self):
         malware = copy.deepcopy(self.valid_malware)
         malware['labels'] += "ransom_ware"
         malware = json.dumps(malware)
         self.assertFalseWithOptions(malware,
-                                    ignored='malware-label')
+                                    disabled='malware-label')
 
     def test_open_vocab_format_space(self):
         malware = copy.deepcopy(self.valid_malware)
         malware['labels'] += "ransom ware"
         malware = json.dumps(malware)
         self.assertFalseWithOptions(malware,
-                                    ignored='malware-label')
+                                    disabled='malware-label')
 
 
 if __name__ == "__main__":
diff --git a/stix2validator/test/marking_definition_tests.py b/stix2validator/test/marking_definition_tests.py
index 2322a8e..b9bffde 100644
--- a/stix2validator/test/marking_definition_tests.py
+++ b/stix2validator/test/marking_definition_tests.py
@@ -37,7 +37,8 @@ class Marking_definitionTestCases(ValidatorTest):
         marking_definition = copy.deepcopy(self.valid_marking_definition)
         marking_definition['definition_type'] = "something"
         marking_definition = json.dumps(marking_definition)
-        self.assertTrueWithOptions(marking_definition, lax=True)
+        self.assertFalseWithOptions(marking_definition)
+        self.assertTrueWithOptions(marking_definition, strict=False)
 
 
 if __name__ == "__main__":
diff --git a/stix2validator/test/tool_tests.py b/stix2validator/test/tool_tests.py
index 11ace03..489bf95 100644
--- a/stix2validator/test/tool_tests.py
+++ b/stix2validator/test/tool_tests.py
@@ -84,9 +84,9 @@ class ToolTestCases(ValidatorTest):
         tool['labels'] += ["something-not-in-vocab"]
         tool_string = json.dumps(tool)
 
-        self.assertFalseWithOptions(tool_string, ignored='1')
-        self.assertFalseWithOptions(tool_string, ignored='2')
-        self.assertTrueWithOptions(tool_string, ignored='1,2')
+        self.assertFalseWithOptions(tool_string, disabled='1')
+        self.assertFalseWithOptions(tool_string, disabled='2')
+        self.assertTrueWithOptions(tool_string, disabled='1,2')
 
 
 if __name__ == "__main__":