Repository: codekie/openapi-examples-validator
Pull request #90 (2020-07-09 21:19:07)

[Snyk] Upgrade json-schema-ref-parser from 9.0.1 to 9.0.2
<h3>Snyk has created this PR to upgrade json-schema-ref-parser from 9.0.1 to 9.0.2.</h3>

  ![merge advice](https://app.snyk.io/badges/merge-advice/?package_manager=npm&package_name=json-schema-ref-parser&from_version=9.0.1&to_version=9.0.2&pr_id=c75d1b7c-115c-4e84-aa8f-6ee0ed37d12d)

:information_source: Keep your dependencies up-to-date. This makes it easier to fix existing vulnerabilities and to more quickly identify and fix newly disclosed vulnerabilities when they affect your project.
<hr/>

- The recommended version is **1 version** ahead of your current version.
- The recommended version was released **a day ago**, on 2020-07-08.


<details>
<summary><b>Release notes</b></summary>
<br/>
  <details>
    <summary>Package name: <b>json-schema-ref-parser</b></summary>
    <ul>
      <li>
        <b>9.0.2</b> - <a href="https://snyk.io/redirect/github/APIDevTools/json-schema-ref-parser/releases/tag/v9.0.2">2020-07-08</a></br><p>release v9.0.2</p>
      </li>
      <li>
        <b>9.0.1</b> - <a href="https://snyk.io/redirect/github/APIDevTools/json-schema-ref-parser/releases/tag/v9.0.1">2020-04-21</a></br><p>release v9.0.1</p>
      </li>
    </ul>
    from <a href="https://snyk.io/redirect/github/APIDevTools/json-schema-ref-parser/releases">json-schema-ref-parser GitHub release notes</a>
  </details>
</details>
<hr/>

**Note:** *You are seeing this because you or someone else with access to this repository has authorized Snyk to open upgrade PRs.*

For more information:  <img src="https://api.segment.io/v1/pixel/track?data=eyJ3cml0ZUtleSI6InJyWmxZcEdHY2RyTHZsb0lYd0dUcVg4WkFRTnNCOUEwIiwiYW5vbnltb3VzSWQiOiJjNzVkMWI3Yy0xMTVjLTRlODQtYWE4Zi02ZWUwZWQzN2QxMmQiLCJldmVudCI6IlBSIHZpZXdlZCIsInByb3BlcnRpZXMiOnsicHJJZCI6ImM3NWQxYjdjLTExNWMtNGU4NC1hYThmLTZlZTBlZDM3ZDEyZCJ9fQ==" width="0" height="0"/>

🧐 [View latest project report](https://app.snyk.io/org/codekie/project/97d884e0-36c0-41cd-8041-ff4dafc1d2b5?utm_source&#x3D;github&amp;utm_medium&#x3D;upgrade-pr)

🛠 [Adjust upgrade PR settings](https://app.snyk.io/org/codekie/project/97d884e0-36c0-41cd-8041-ff4dafc1d2b5/settings/integration?utm_source&#x3D;github&amp;utm_medium&#x3D;upgrade-pr)

🔕 [Ignore this dependency or unsubscribe from future upgrade PRs](https://app.snyk.io/org/codekie/project/97d884e0-36c0-41cd-8041-ff4dafc1d2b5/settings/integration?pkg&#x3D;json-schema-ref-parser&amp;utm_source&#x3D;github&amp;utm_medium&#x3D;upgrade-pr#auto-dep-upgrades)

<!--- (snyk:metadata:{"prId":"c75d1b7c-115c-4e84-aa8f-6ee0ed37d12d","dependencies":[{"name":"json-schema-ref-parser","from":"9.0.1","to":"9.0.2"}],"packageManager":"npm","type":"auto","projectUrl":"https://app.snyk.io/org/codekie/project/97d884e0-36c0-41cd-8041-ff4dafc1d2b5?utm_source=github&utm_medium=upgrade-pr","projectPublicId":"97d884e0-36c0-41cd-8041-ff4dafc1d2b5","env":"prod","prType":"upgrade","vulns":[],"issuesToFix":[],"upgrade":[],"upgradeInfo":{"versionsDiff":1,"publishedDate":"2020-07-08T13:33:02.509Z"},"templateVariants":["merge-advice-badge-shown"],"hasFixes":false,"isMajorUpgrade":false,"isBreakingChange":false}) --->


coveralls: 
[![Coverage Status](https://coveralls.io/builds/31976902/badge)](https://coveralls.io/builds/31976902)

Coverage remained the same at 100.0% when pulling **ebd62fa435f82ebebf58233cb6a93d143e958248 on snyk-upgrade-5f83f8e1d284d569333712b4d1f92cd4** into **5d7042038db699fc1920b35cd0c6df0398b47267 on master**.


Patch:
diff --git a/README.md b/README.md
index 3784926..17b7283 100644
--- a/README.md
+++ b/README.md
@@ -40,6 +40,7 @@ Options:
   -c, --cwd-to-mapping-file                  changes to the directory of the mapping-file, before resolving the
                                              example's paths. Use this option, if your mapping-files use relative paths
                                              for the examples
+  -n, --no-additional-properties             don't allow properties that are not described in the schema
   -h, --help                                 output usage information
 ````
 
@@ -88,8 +89,9 @@ Sample output of validation errors:
 Caveat
 ------
 
-The formats `int32`, `float` and `double` are supported for the type `number`. The format `int64` is only available
-for the type `string`, though (due to the precision-limitations of Javascript).
+- The formats `int32`, `float` and `double` are supported for the type `number`. The format `int64` is only available
+  for the type `string`, though (due to the precision-limitations of Javascript).
+- The option `--no-additional-properties` does not work, if `allOf` is used to combine subschemas.
 
 Test
 ----
diff --git a/package-lock.json b/package-lock.json
index e76ddc6..bafa40c 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -5,9 +5,9 @@
   "requires": true,
   "dependencies": {
     "@apidevtools/json-schema-ref-parser": {
-      "version": "9.0.1",
-      "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.0.1.tgz",
-      "integrity": "sha512-Qsdz0W0dyK84BuBh5KZATWXOtVDXIF2EeNRzpyWblPUeAmnIokwWcwrpAm5pTPMjuWoIQt9C67X3Af1OlL6oSw==",
+      "version": "9.0.2",
+      "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.0.2.tgz",
+      "integrity": "sha512-Q8QNyluEhbCCZS6F1wLqVkp5GuUHwq4qveZmZWE2OZA7dTEjyg3dkgxAy6fUzDNaEzzcNrY3D58cfph4881nlg==",
       "requires": {
         "@jsdevtools/ono": "^7.1.2",
         "call-me-maybe": "^1.0.1",
@@ -3106,9 +3106,9 @@
       }
     },
     "ajv": {
-      "version": "6.12.2",
-      "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.2.tgz",
-      "integrity": "sha512-k+V+hzjm5q/Mr8ef/1Y9goCmlsK4I6Sm74teeyGvFk1XrOsbsKLjEdrvny42CZ+a8sXbk8KWpY/bDwS+FLL2UQ==",
+      "version": "6.12.3",
+      "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.3.tgz",
+      "integrity": "sha512-4K0cK3L1hsqk9xIb2z9vs/XU+PGJZ9PNpJRDS9YLzmNdX6jmVPfamLvTJr0aDAusnHyCHO6MjzlkAsgtqp9teA==",
       "requires": {
         "fast-deep-equal": "^3.1.1",
         "fast-json-stable-stringify": "^2.0.0",
@@ -5595,9 +5595,9 @@
       "dev": true
     },
     "fast-deep-equal": {
-      "version": "3.1.1",
-      "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz",
-      "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA=="
+      "version": "3.1.3",
+      "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+      "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
     },
     "fast-json-stable-stringify": {
       "version": "2.1.0",
@@ -7868,11 +7868,11 @@
       "dev": true
     },
     "json-schema-ref-parser": {
-      "version": "9.0.1",
-      "resolved": "https://registry.npmjs.org/json-schema-ref-parser/-/json-schema-ref-parser-9.0.1.tgz",
-      "integrity": "sha512-KLrCjRjW5hMXxsX4osVBWpwixXL9NtICfpyNNS0eHguN5mP/I4UatI7i7PFS8jU94b1NHF4EbirACdCn0RFPBA==",
+      "version": "9.0.2",
+      "resolved": "https://registry.npmjs.org/json-schema-ref-parser/-/json-schema-ref-parser-9.0.2.tgz",
+      "integrity": "sha512-IppBL4rZhcvDofyOLpI+dg5Twlf48RkQpK1bQUUogfX7g3R5JX487lYJiXmgXDB+qp4pOj1rbJHbT6wM3jGm1Q==",
       "requires": {
-        "@apidevtools/json-schema-ref-parser": "9.0.1"
+        "@apidevtools/json-schema-ref-parser": "9.0.2"
       }
     },
     "json-schema-traverse": {
diff --git a/package.json b/package.json
index 1ac05f9..257093f 100644
--- a/package.json
+++ b/package.json
@@ -68,13 +68,13 @@
     "webpack-cli": "^3.3.12"
   },
   "dependencies": {
-    "ajv": "^6.12.2",
+    "ajv": "^6.12.3",
     "ajv-oai": "1.2.0",
     "commander": "^5.1.0",
     "errno": "0.1.7",
     "glob": "^7.1.6",
     "json-pointer": "0.6.0",
-    "json-schema-ref-parser": "^9.0.1",
+    "json-schema-ref-parser": "^9.0.2",
     "jsonpath-plus": "^4.0.0",
     "lodash.clonedeep": "^4.5.0",
     "lodash.flatmap": "^4.5.0",
diff --git a/src/cli.js b/src/cli.js
index 69a41f6..e456a51 100755
--- a/src/cli.js
+++ b/src/cli.js
@@ -24,6 +24,7 @@ program
         + ' file-path(s) to examples as value. If wildcards are used, the parameter has to be put in quotes.')
     .option('-c, --cwd-to-mapping-file', "changes to the directory of the mapping-file, before resolving the example's"
         + ' paths. Use this option, if your mapping-files use relative paths for the examples')
+    .option('-n, --no-additional-properties', 'don\'t allow properties that are not described in the schema')
     .action(processAction);
 program.on('--help', () => {
     console.log('\n\n  Example for external example-file:\n');
@@ -35,17 +36,18 @@ program.parse(process.argv);
 // IMPLEMENTATION DETAILS
 
 async function processAction(filepath, options) {
-    const { schemaJsonpath, exampleFilepath, mappingFilepath, cwdToMappingFile } = options;
+    const { schemaJsonpath, exampleFilepath, mappingFilepath, cwdToMappingFile } = options,
+        noAdditionalProperties = !options.additionalProperties;
     let result;
     if (mappingFilepath) {
         console.log('Validating with mapping file');
-        result = await validateExamplesByMap(filepath, mappingFilepath, { cwdToMappingFile });
+        result = await validateExamplesByMap(filepath, mappingFilepath, { cwdToMappingFile, noAdditionalProperties });
     } else if (schemaJsonpath && exampleFilepath) {
         console.log('Validating single external example');
-        result = await validateExample(filepath, schemaJsonpath, exampleFilepath);
+        result = await validateExample(filepath, schemaJsonpath, exampleFilepath, { noAdditionalProperties });
     } else {
         console.log('Validating examples');
-        result = await validateFile(filepath);
+        result = await validateFile(filepath, { noAdditionalProperties });
     }
     _handleResult(result);
 }
diff --git a/src/impl/service/disallow-additional-properties.js b/src/impl/service/disallow-additional-properties.js
new file mode 100644
index 0000000..f697450
--- /dev/null
+++ b/src/impl/service/disallow-additional-properties.js
@@ -0,0 +1,101 @@
+const { JSONPath: jsonPath } = require('jsonpath-plus'),
+    ResultType = require('../../const/result-type');
+
+const JSON_PATHS__OBJECTS = [
+    '$..application/json.schema',
+    '$..schema..[?(@.properties && (@property === "schema" || @property === "items" || @.type === "object"))]'
+];
+
+module.exports = {
+    setNoAdditionalProperties
+};
+
+/**
+ * @typedef {{
+ *     path: String,
+ *     value: Object,
+ *     parent: Object,
+ *     parentProperty: String,
+ *     hasArrExpr: Boolean
+ * }} JsonPathMatchData
+ */
+
+/**
+ * Callback that is applied to a JSONPath-match.
+ * @callback JsonPathMatchCallback
+ * @param {Object}              value       Value of the matched property
+ * @param {String}              resultType  Result-type of the query
+ * @param {JsonPathMatchData}   data        Object that contains additional data to the match
+ */
+
+/**
+ * Sets the flag to indicate that it doesn't allow properties that are not described in the schema
+ * @param {Object}                  openApiSpec         The to-be-modified schema
+ * @param {Array.<String>}          [examplePaths=[]]   The paths to the examples, which's content must not be modified
+ * @param {JsonPathMatchCallback}   [callback=_callbackObjectTypeForNoAdditionalProperties] Function to be called on a
+ *                                                      match
+ * @private
+ */
+function setNoAdditionalProperties(openApiSpec, examplePaths = [],
+    callback = _callbackObjectTypeForNoAdditionalProperties
+) {
+    // Find all matches
+    const paths = new Set();
+    JSON_PATHS__OBJECTS.forEach(jsPath => {
+        _find(openApiSpec, jsPath)
+            .forEach(match => paths.add(match));
+    });
+    // Exclude examples
+    _excludeExamples(openApiSpec, paths, examplePaths);
+    // Set flag
+    for (const jsPath of paths) {
+        _find(openApiSpec, jsPath, ResultType.value, callback);
+    }
+}
+
+/**
+ * Callback, to set the `additionalProperties` to `false` the object-schemas
+ * @type JsonPathMatchCallback
+ * @private
+ */
+function _callbackObjectTypeForNoAdditionalProperties(value) {
+    value.additionalProperties = false;
+}
+
+/**
+ * Find matching elements in JSON.
+ * @param {Object}                  json                JSON to be searched
+ * @param {String}                  path                JSON-path to search
+ * @param {String}                  [resultType="path"] Result-type of the query
+ * @param {JsonPathMatchCallback}   [callback]          Function to be called on a match
+ * @returns {any} Result of the query, depending on the `resultType`
+ * @private
+ */
+function _find(json, path, resultType = ResultType.path, callback) {
+    return jsonPath({
+        json,
+        path,
+        flatten: true,
+        resultType,
+        callback
+    });
+}
+
+/**
+ * Remove JSON-paths from `paths` that are included in `examplePaths`
+ * @param {Object}          openApiSpec     Open-API spec to search in
+ * @param {Set.<String>}    paths           Paths where the examples have to be removed from
+ * @param {Array.<String>}  examplePaths    JSON-paths of the examples
+ * @private
+ */
+function _excludeExamples(openApiSpec, paths, examplePaths) {
+    examplePaths
+        .forEach(examplePath => {
+            _find(openApiSpec, examplePath)
+                .forEach(exampleMatch => {
+                    for (const jsPath of paths) {
+                        jsPath.startsWith(exampleMatch) && paths.delete(jsPath);
+                    }
+                });
+        });
+}
diff --git a/src/impl/v2/index.js b/src/impl/v2/index.js
index 34b86e2..41ac223 100644
--- a/src/impl/v2/index.js
+++ b/src/impl/v2/index.js
@@ -2,7 +2,9 @@
  * Contains validation-logic that is specific to V2 of the OpenAPI-spec
  */
 
-const { JSONPath: jsonPath } = require('jsonpath-plus');
+const { JSONPath: jsonPath } = require('jsonpath-plus'),
+    { setNoAdditionalProperties } = require('../service/disallow-additional-properties'),
+    cloneDeep = require('lodash.clonedeep');
 
 // CONSTANTS
 
@@ -44,12 +46,14 @@ function buildValidationMap(pathsExamples) {
 /**
  * Pre-processes the OpenAPI-spec, for further use.
  * The passed spec won't be modified. If a modification happens, a modified copy will be returned.
- * @param {Object}  openapiSpec     The OpenAPI-spec as JSON-schema
+ * @param {Object}  openapiSpec                     The OpenAPI-spec as JSON-schema
+ * @param {boolean} [noAdditionalProperties=false]  Don't allow properties that are not defined in the schema
  * @return {Object} The prepared OpenAPI-spec
  */
-function prepare(openapiSpec) {
-    // No pre-processing yet, so we return the original
-    return openapiSpec;
+function prepare(openapiSpec, { noAdditionalProperties } = {}) {
+    const openapiSpecCopy = cloneDeep(openapiSpec);
+    noAdditionalProperties && setNoAdditionalProperties(openapiSpecCopy, getJsonPathsToExamples());
+    return openapiSpecCopy;
 }
 
 /**
diff --git a/src/impl/v3/index.js b/src/impl/v3/index.js
index 107e88d..cf29e85 100644
--- a/src/impl/v3/index.js
+++ b/src/impl/v3/index.js
@@ -3,7 +3,9 @@
  */
 
 const { JSONPath: jsonPath } = require('jsonpath-plus'),
-    { ApplicationError, ErrorType } = require('../../application-error');
+    cloneDeep = require('lodash.clonedeep'),
+    { ApplicationError, ErrorType } = require('../../application-error'),
+    { setNoAdditionalProperties } = require('../service/disallow-additional-properties');
 
 // CONSTANTS
 
@@ -74,13 +76,13 @@ function buildValidationMap(pathsExamples) {
  * Pre-processes the OpenAPI-spec, for further use.
  * The passed spec won't be modified. If a modification happens, a modified copy will be returned.
  * @param {Object}  openapiSpec     The OpenAPI-spec as JSON-schema
+ * @param {boolean} [noAdditionalProperties=false]  Don't allow properties that are not defined in the schema
  * @return {Object} The prepared OpenAPI-spec
  */
-function prepare(openapiSpec) {
-    // None yet. I added this to implement `nullable` until I figured there was a property for that.
-    // I'll leave this here for now, as pre-processing might become necessary for other things.
-    // A "cloneDeep"-function will be required though (eg. `lodash.clonedeep`-dependency)
-    return openapiSpec;
+function prepare(openapiSpec, { noAdditionalProperties } = {}) {
+    const openapiSpecCopy = cloneDeep(openapiSpec);
+    noAdditionalProperties && setNoAdditionalProperties(openapiSpecCopy, getJsonPathsToExamples());
+    return openapiSpecCopy;
 }
 
 /**
diff --git a/src/index.js b/src/index.js
index d05d76f..db354ea 100644
--- a/src/index.js
+++ b/src/index.js
@@ -11,6 +11,7 @@ const
     glob = require('glob'),
     yaml = require('yaml'),
     { JSONPath: jsonPath } = require('jsonpath-plus'),
+    refParser = require('json-schema-ref-parser'),
     { createError } = require('errno').custom,
     ResultType = require('./const/result-type'),
     { getValidatorFactory, compileValidate } = require('./validator'),
@@ -91,11 +92,13 @@ module.exports = {
 /**
  * Validates OpenAPI-spec with embedded examples.
  * @param {Object}  openapiSpec OpenAPI-spec
+ * @param {boolean} [noAdditionalProperties=false]  Don't allow properties that are not defined in the schema
  * @returns {ValidationResponse}
  */
-function validateExamples(openapiSpec) {
+async function validateExamples(openapiSpec, { noAdditionalProperties } = {}) {
     const impl = Determiner.getImplementation(openapiSpec);
-    openapiSpec = impl.prepare(openapiSpec);
+    openapiSpec = await refParser.dereference(openapiSpec);
+    openapiSpec = impl.prepare(openapiSpec, { noAdditionalProperties });
     let pathsExamples = impl.getJsonPathsToExamples()
         .reduce((res, pathToExamples) => {
             return res.concat(_extractExamplePaths(openapiSpec, pathToExamples));
@@ -105,17 +108,18 @@ function validateExamples(openapiSpec) {
 
 /**
  * Validates OpenAPI-spec with embedded examples.
- * @param {string}  filePath    File-path to the OpenAPI-spec
+ * @param {string}  filePath                        File-path to the OpenAPI-spec
+ * @param {boolean} [noAdditionalProperties=false]  Don't allow properties that are not defined in the schema
  * @returns {ValidationResponse}
  */
-async function validateFile(filePath) {
+async function validateFile(filePath, { noAdditionalProperties } = {}) {
     let openapiSpec = null;
     try {
         openapiSpec = await _parseSpec(filePath);
     } catch (err) {
         return createValidationResponse({ errors: [ApplicationError.create(err)] });
     }
-    return validateExamples(openapiSpec);
+    return validateExamples(openapiSpec, { noAdditionalProperties });
 }
 
 /**
@@ -126,9 +130,12 @@ async function validateFile(filePath) {
  *                                              to external examples
  * @param {boolean} [cwdToMappingFile=false]    Change working directory for resolving the example-paths (relative to
  *                                              the mapping-file)
+ * @param {boolean} [noAdditionalProperties=false] Don't allow properties that are not defined in the schema
  * @returns {ValidationResponse}
  */
-async function validateExamplesByMap(filePathSchema, globMapExternalExamples, { cwdToMappingFile } = {}) {
+async function validateExamplesByMap(filePathSchema, globMapExternalExamples,
+    { cwdToMappingFile, noAdditionalProperties } = {}
+) {
     let matchingFilePathsMapping = 0;
     const filePathsMaps = glob.sync(
         globMapExternalExamples,
@@ -145,7 +152,7 @@ async function validateExamplesByMap(filePathSchema, globMapExternalExamples, {
             mapExternalExamples = JSON.parse(fs.readFileSync(filePathMapExternalExamples, 'utf-8'));
             openapiSpec = await _parseSpec(filePathSchema);
             openapiSpec = Determiner.getImplementation(openapiSpec)
-                .prepare(openapiSpec);
+                .prepare(openapiSpec, { noAdditionalProperties });
         } catch (err) {
             responses.push(createValidationResponse({ errors: [ApplicationError.create(err)] }));
             continue;
@@ -181,12 +188,13 @@ async function validateExamplesByMap(filePathSchema, globMapExternalExamples, {
 
 /**
  * Validates a single external example.
- * @param {String}  filePathSchema      File-path to the OpenAPI-spec
- * @param {String}  pathSchema          JSON-path to the schema
- * @param {String}  filePathExample     File-path to the external example-file
+ * @param {String}  filePathSchema                  File-path to the OpenAPI-spec
+ * @param {String}  pathSchema                      JSON-path to the schema
+ * @param {String}  filePathExample                 File-path to the external example-file
+ * @param {boolean} [noAdditionalProperties=false]  Don't allow properties that are not described in the schema
  * @returns {ValidationResponse}
  */
-async function validateExample(filePathSchema, pathSchema, filePathExample) {
+async function validateExample(filePathSchema, pathSchema, filePathExample, { noAdditionalProperties } = {}) {
     let example = null,
         schema = null,
         openapiSpec = null;
@@ -194,7 +202,7 @@ async function validateExample(filePathSchema, pathSchema, filePathExample) {
         example = JSON.parse(fs.readFileSync(filePathExample, 'utf-8'));
         openapiSpec = await _parseSpec(filePathSchema);
         openapiSpec = Determiner.getImplementation(openapiSpec)
-            .prepare(openapiSpec);
+            .prepare(openapiSpec, { noAdditionalProperties });
         schema = _extractSchema(pathSchema, openapiSpec);
     } catch (err) {
         return createValidationResponse({ errors: [ApplicationError.create(err)] });


Test patch:
diff --git a/test/data/output-help.js b/test/data/output-help.js
index 160fb5f..e8f1083 100644
--- a/test/data/output-help.js
+++ b/test/data/output-help.js
@@ -12,6 +12,7 @@ Options:
   -e, --example-filepath <example-filepath>  file path to example file, to be validated
   -m, --mapping-filepath <mapping-filepath>  file path to map, containing schema-paths as key and the file-path(s) to examples as value. If wildcards are used, the parameter has to be put in quotes.
   -c, --cwd-to-mapping-file                  changes to the directory of the mapping-file, before resolving the example's paths. Use this option, if your mapping-files use relative paths for the examples
+  -n, --no-additional-properties             don't allow properties that are not described in the schema
   -h, --help                                 display help for command
 
 
diff --git a/test/data/output/api-with-examples-and-additional-properties.js b/test/data/output/api-with-examples-and-additional-properties.js
new file mode 100644
index 0000000..f5df5aa
--- /dev/null
+++ b/test/data/output/api-with-examples-and-additional-properties.js
@@ -0,0 +1,8 @@
+module.exports.value = `Validating examples
+Schemas with examples found: 2
+Examples without schema found: 0
+Total examples found: 2
+
+Errors found.
+
+`;
diff --git a/test/data/v3/additional-properties/errors-list.json b/test/data/v3/additional-properties/errors-list.json
new file mode 100644
index 0000000..1ed4afe
--- /dev/null
+++ b/test/data/v3/additional-properties/errors-list.json
@@ -0,0 +1,24 @@
+[
+  {
+    "type": "Validation",
+    "message": "should NOT have additional properties",
+    "keyword": "additionalProperties",
+    "dataPath": "[0]",
+    "schemaPath": "#/items/additionalProperties",
+    "params": {
+      "additionalProperty": "owner"
+    },
+    "exampleFilePath": "/test/data/v3/additional-properties/example-list-with-additional-properties.json"
+  },
+  {
+    "type": "Validation",
+    "message": "should NOT have additional properties",
+    "keyword": "additionalProperties",
+    "dataPath": "[0]",
+    "schemaPath": "#/items/additionalProperties",
+    "params": {
+      "additionalProperty": "age"
+    },
+    "exampleFilePath": "/test/data/v3/additional-properties/example-list-with-additional-properties.json"
+  }
+]
diff --git a/test/data/v3/additional-properties/errors-map-external-examples.json b/test/data/v3/additional-properties/errors-map-external-examples.json
new file mode 100644
index 0000000..154aca6
--- /dev/null
+++ b/test/data/v3/additional-properties/errors-map-external-examples.json
@@ -0,0 +1,50 @@
+[
+  {
+    "type": "Validation",
+    "message": "should NOT have additional properties",
+    "keyword": "additionalProperties",
+    "mapFilePath": "/test/data/v3/additional-properties/map-external-examples-with-additional-properties.json",
+    "dataPath": "[0]",
+    "schemaPath": "#/items/additionalProperties",
+    "params": {
+      "additionalProperty": "owner"
+    },
+    "exampleFilePath": "test/data/v3/additional-properties/example-list-with-additional-properties.json"
+  },
+  {
+    "type": "Validation",
+    "message": "should NOT have additional properties",
+    "keyword": "additionalProperties",
+    "mapFilePath": "/test/data/v3/additional-properties/map-external-examples-with-additional-properties.json",
+    "dataPath": "[0]",
+    "schemaPath": "#/items/additionalProperties",
+    "params": {
+      "additionalProperty": "age"
+    },
+    "exampleFilePath": "test/data/v3/additional-properties/example-list-with-additional-properties.json"
+  },
+  {
+    "type": "Validation",
+    "message": "should NOT have additional properties",
+    "keyword": "additionalProperties",
+    "mapFilePath": "/test/data/v3/additional-properties/map-external-examples-with-additional-properties.json",
+    "dataPath": "",
+    "schemaPath": "#/additionalProperties",
+    "params": {
+      "additionalProperty": "owner"
+    },
+    "exampleFilePath": "test/data/v3/additional-properties/example-single-with-additional-properties.json"
+  },
+  {
+    "type": "Validation",
+    "message": "should NOT have additional properties",
+    "keyword": "additionalProperties",
+    "mapFilePath": "/test/data/v3/additional-properties/map-external-examples-with-additional-properties.json",
+    "dataPath": "",
+    "schemaPath": "#/additionalProperties",
+    "params": {
+      "additionalProperty": "age"
+    },
+    "exampleFilePath": "test/data/v3/additional-properties/example-single-with-additional-properties.json"
+  }
+]
diff --git a/test/data/v3/additional-properties/errors-schema-with-examples.json b/test/data/v3/additional-properties/errors-schema-with-examples.json
new file mode 100644
index 0000000..d6fffef
--- /dev/null
+++ b/test/data/v3/additional-properties/errors-schema-with-examples.json
@@ -0,0 +1,46 @@
+[
+  {
+    "type": "Validation",
+    "message": "should NOT have additional properties",
+    "keyword": "additionalProperties",
+    "dataPath": "",
+    "schemaPath": "#/additionalProperties",
+    "params": {
+      "additionalProperty": "owner"
+    },
+    "examplePath": "/paths/~1pets~1{petId}/get/responses/200/content/application~1json/example"
+  },
+  {
+    "type": "Validation",
+    "message": "should NOT have additional properties",
+    "keyword": "additionalProperties",
+    "dataPath": "[0]",
+    "schemaPath": "#/items/additionalProperties",
+    "params": {
+      "additionalProperty": "owner"
+    },
+    "examplePath": "/paths/~1pets/get/responses/200/content/application~1json/examples/single/value"
+  },
+  {
+    "type": "Validation",
+    "message": "should NOT have additional properties",
+    "keyword": "additionalProperties",
+    "dataPath": "[0]",
+    "schemaPath": "#/items/additionalProperties",
+    "params": {
+      "additionalProperty": "age"
+    },
+    "examplePath": "/paths/~1pets/get/responses/200/content/application~1json/examples/single/value"
+  },
+  {
+    "type": "Validation",
+    "message": "should NOT have additional properties",
+    "keyword": "additionalProperties",
+    "dataPath": "",
+    "schemaPath": "#/additionalProperties",
+    "params": {
+      "additionalProperty": "age"
+    },
+    "examplePath": "/paths/~1pets~1{petId}/get/responses/200/content/application~1json/example"
+  }
+]
diff --git a/test/data/v3/additional-properties/errors-single.json b/test/data/v3/additional-properties/errors-single.json
new file mode 100644
index 0000000..8c0c30e
--- /dev/null
+++ b/test/data/v3/additional-properties/errors-single.json
@@ -0,0 +1,24 @@
+[
+  {
+    "type": "Validation",
+    "message": "should NOT have additional properties",
+    "keyword": "additionalProperties",
+    "dataPath": "",
+    "schemaPath": "#/additionalProperties",
+    "params": {
+      "additionalProperty": "owner"
+    },
+    "exampleFilePath": "/test/data/v3/additional-properties/example-single-with-additional-properties.json"
+  },
+  {
+    "type": "Validation",
+    "message": "should NOT have additional properties",
+    "keyword": "additionalProperties",
+    "dataPath": "",
+    "schemaPath": "#/additionalProperties",
+    "params": {
+      "additionalProperty": "age"
+    },
+    "exampleFilePath": "/test/data/v3/additional-properties/example-single-with-additional-properties.json"
+  }
+]
diff --git a/test/data/v3/additional-properties/example-list-with-additional-properties.json b/test/data/v3/additional-properties/example-list-with-additional-properties.json
new file mode 100644
index 0000000..2c7d0bd
--- /dev/null
+++ b/test/data/v3/additional-properties/example-list-with-additional-properties.json
@@ -0,0 +1,14 @@
+[
+  {
+    "id": 0,
+    "name": "Herbert",
+    "tag": "Doggo",
+    "owner": "John",
+    "age": 5,
+    "schema": {
+      "properties": {
+        "color": "black"
+      }
+    }
+  }
+]
diff --git a/test/data/v3/additional-properties/example-single-with-additional-properties.json b/test/data/v3/additional-properties/example-single-with-additional-properties.json
new file mode 100644
index 0000000..69e5b4a
--- /dev/null
+++ b/test/data/v3/additional-properties/example-single-with-additional-properties.json
@@ -0,0 +1,12 @@
+{
+  "id": 0,
+  "name": "Herbert",
+  "tag": "Doggo",
+  "owner": "John",
+  "age": 5,
+  "schema": {
+    "properties": {
+      "color": "black"
+    }
+  }
+}
diff --git a/test/data/v3/additional-properties/map-external-examples-with-additional-properties.json b/test/data/v3/additional-properties/map-external-examples-with-additional-properties.json
new file mode 100644
index 0000000..775c91d
--- /dev/null
+++ b/test/data/v3/additional-properties/map-external-examples-with-additional-properties.json
@@ -0,0 +1,7 @@
+{
+  "$.paths./pets.get.responses.200.content.application/json.schema": [
+    "test/data/v3/additional-properties/example-list-with-additional-properties.json"
+  ],
+  "$.paths./pets/{petId}.get.responses.200.content.application/json.schema":
+    "test/data/v3/additional-properties/example-single-with-additional-properties.json"
+}
diff --git a/test/data/v3/additional-properties/schema-with-examples.yaml b/test/data/v3/additional-properties/schema-with-examples.yaml
new file mode 100644
index 0000000..5cf2c0d
--- /dev/null
+++ b/test/data/v3/additional-properties/schema-with-examples.yaml
@@ -0,0 +1,123 @@
+openapi: 3.0.0
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+  license:
+    name: MIT
+servers:
+  - url: 'http://petstore.swagger.io/v1'
+paths:
+  /pets:
+    get:
+      summary: List all pets
+      operationId: listPets
+      responses:
+        '200':
+          description: An array of pets
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/Pets'
+              examples:
+                single:
+                  value:
+                    - id: 0
+                      name: Herbert
+                      tag: Doggo
+                      owner: John
+                      age: 5
+                      schema:
+                        properties:
+                          color: black
+        default:
+          description: unexpected error
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/Error'
+    post:
+      summary: Create a pet
+      operationId: createPets
+      tags:
+        - pets
+      responses:
+        '201':
+          description: Null response
+        default:
+          description: unexpected error
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/Error'
+  '/pets/{petId}':
+    get:
+      summary: Info for a specific pet
+      operationId: showPetById
+      parameters:
+        - name: petId
+          in: path
+          required: true
+          description: The id of the pet to retrieve
+          schema:
+            type: string
+      responses:
+        '200':
+          description: Expected response to a valid request
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/Pet'
+              example:
+                id: 0
+                name: Herbert
+                tag: Doggo
+                owner: John
+                age: 5
+                schema:
+                  properties:
+                    color: black
+        default:
+          description: unexpected error
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/Error'
+components:
+  schemas:
+    Pet:
+      required:
+        - id
+        - name
+      type: object
+      properties:
+        id:
+          type: number
+        name:
+          type: string
+        tag:
+          type: string
+        # This intentionally is a property called `schema`
+        schema:
+          type: object
+          properties:
+            # This intentionally is a property called `properties`
+            properties:
+              type: object
+              # This should not be extended with an `additionalProperties: false`
+              properties:
+                color:
+                  type: string
+
+    Pets:
+      type: array
+      items:
+        $ref: '#/components/schemas/Pet'
+    Error:
+      required:
+        - code
+        - message
+      properties:
+        code:
+          type: number
+        message:
+          type: string
diff --git a/test/data/v3/additional-properties/schema.yaml b/test/data/v3/additional-properties/schema.yaml
new file mode 100644
index 0000000..cc683be
--- /dev/null
+++ b/test/data/v3/additional-properties/schema.yaml
@@ -0,0 +1,103 @@
+openapi: 3.0.0
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+  license:
+    name: MIT
+servers:
+  - url: 'http://petstore.swagger.io/v1'
+paths:
+  /pets:
+    get:
+      summary: List all pets
+      operationId: listPets
+      responses:
+        '200':
+          description: An array of pets
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/Pets'
+        default:
+          description: unexpected error
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/Error'
+    post:
+      summary: Create a pet
+      operationId: createPets
+      tags:
+        - pets
+      responses:
+        '201':
+          description: Null response
+        default:
+          description: unexpected error
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/Error'
+  '/pets/{petId}':
+    get:
+      summary: Info for a specific pet
+      operationId: showPetById
+      parameters:
+        - name: petId
+          in: path
+          required: true
+          description: The id of the pet to retrieve
+          schema:
+            type: string
+      responses:
+        '200':
+          description: Expected response to a valid request
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/Pet'
+        default:
+          description: unexpected error
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/Error'
+components:
+  schemas:
+    Pet:
+      required:
+        - id
+        - name
+      type: object
+      properties:
+        id:
+          type: number
+        name:
+          type: string
+        tag:
+          type: string
+        # This intentionally is a property called `schema`
+        schema:
+          type: object
+          properties:
+            # This intentionally is a property called `properties`
+            properties:
+              type: object
+              # This should not be extended with an `additionalProperties: false`
+              properties:
+                color:
+                  type: string
+
+    Pets:
+      type: array
+      items:
+        $ref: '#/components/schemas/Pet'
+    Error:
+      required:
+        - code
+        - message
+      properties:
+        code:
+          type: number
+        message:
+          type: string
diff --git a/test/specs/cli.js b/test/specs/cli.js
index 23f5439..454f52a 100644
--- a/test/specs/cli.js
+++ b/test/specs/cli.js
@@ -88,4 +88,30 @@ describe('CLI-module', function() {
             );
         });
     });
+    describe('with additional properties', function() {
+        it('should show no error without providing the flag', function(done) {
+            const pathSchema = getPathOfTestData('v3/additional-properties/schema-with-examples.yaml', true);
+            exec(`${ CMD__RUN } ${ pathSchema }`,
+                (err, stdout, stderr) => {
+                    stdout.should.not.equal('');
+                    stderr.should.equal('');
+                    done();
+                }
+            );
+        });
+        it('should show error with providing the flag', function(done) {
+            const pathSchema = getPathOfTestData('v3/additional-properties/schema-with-examples.yaml', true);
+            exec(`${ CMD__RUN } -n ${ pathSchema }`,
+                (err, stdout, stderr) => {
+                    stdout.should.equal(require('../data/output/api-with-examples-and-additional-properties').value);
+                    stderr.should.equal(JSON.stringify(
+                        require('../data/v3/additional-properties/errors-schema-with-examples.json'),
+                        null,
+                        '    '
+                    ));
+                    done();
+                }
+            );
+        });
+    });
 });
diff --git a/test/specs/impl/service/schema-extender.js b/test/specs/impl/service/schema-extender.js
new file mode 100644
index 0000000..8cb7b92
--- /dev/null
+++ b/test/specs/impl/service/schema-extender.js
@@ -0,0 +1,293 @@
+const { setNoAdditionalProperties } = require('../../../../src/impl/service/disallow-additional-properties'),
+    { getJsonPathsToExamples } = require('../../../../src/impl/v3/index');
+
+const SCHEMA = _getSchema(),
+    JSON_PATHS__OBJECTS = _getPaths();
+
+describe('The schema extender', function() {
+    it('should find the right matches', function() {
+        const paths = [];
+        setNoAdditionalProperties(SCHEMA, getJsonPathsToExamples(), (value, resultType, data) => {
+            paths.push(data.path);
+        });
+        paths.sort().should.deep.equal(JSON_PATHS__OBJECTS.sort());
+    });
+});
+
+function _getSchema() {
+    return {
+        'openapi': '3.0.0',
+        'info': {
+            'version': '1.0.0',
+            'title': 'Swagger Petstore',
+            'license': {
+                'name': 'MIT'
+            }
+        },
+        'servers': [
+            {
+                'url': 'http://petstore.swagger.io/v1'
+            }
+        ],
+        'paths': {
+            '/pets': {
+                'get': {
+                    'summary': 'List all pets',
+                    'operationId': 'listPets',
+                    'responses': {
+                        '200': {
+                            'description': 'An array of pets',
+                            'content': {
+                                'application/json': {
+// MAYBE (not necessary, but doesn't break if it's included)
+// I haven't been able to write a JSONPath-query, to exclude it (`$..application/json.schema` for the type `array`)
+                                    'schema': {
+                                        'type': 'array',
+// TO BE FOUND
+                                        'items': {
+                                            'required': [
+                                                'id',
+                                                'name'
+                                            ],
+                                            'properties': {
+                                                'id': {
+                                                    'type': 'number'
+                                                },
+                                                'name': {
+                                                    'type': 'string'
+                                                },
+                                                'tag': {
+                                                    'type': 'string'
+                                                },
+// TO BE FOUND
+                                                'schema': {
+                                                    'type': 'object',
+                                                    'properties': {
+// TO BE FOUND
+                                                        'properties': {
+                                                            'type': 'object',
+// NOT TO BE FOUND
+                                                            'properties': {
+                                                                'type': {
+                                                                    'type': 'object'
+                                                                },
+                                                                'color': {
+                                                                    'type': 'string'
+                                                                },
+// TO BE FOUND
+                                                                'properties': {
+                                                                    'type': 'object',
+                                                                    'properties': {
+                                                                        'foo': {
+                                                                            'type': 'number'
+                                                                        }
+                                                                    }
+                                                                }
+                                                            }
+                                                        }
+                                                    }
+                                                }
+                                            }
+                                        }
+                                    },
+                                    'examples': {
+                                        'single': {
+                                            'value': [
+                                                {
+                                                    'id': 0,
+                                                    'name': 'Herbert',
+                                                    'tag': 'Doggo',
+                                                    'owner': 'John',
+                                                    'age': 5,
+// NOT TO BE FOUND (examples-sub-path)
+                                                    'schema': {
+// NOT TO BE FOUND (examples-sub-path)
+                                                        'properties': {
+                                                            'color': 'black',
+                                                            'type': 'object',
+                                                            'properties': {
+                                                                'foo': 1
+                                                            }
+                                                        }
+                                                    }
+                                                }
+                                            ]
+                                        }
+                                    }
+                                }
+                            }
+                        },
+                        'default': {
+                            'description': 'unexpected error',
+                            'content': {
+                                'application/json': {
+// TO BE FOUND
+                                    'schema': {
+                                        'required': [
+                                            'code',
+                                            'message'
+                                        ],
+                                        'properties': {
+                                            'code': {
+                                                'type': 'number'
+                                            },
+                                            'message': {
+                                                'type': 'string'
+                                            }
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                },
+                'post': {
+                    'summary': 'Create a pet',
+                    'operationId': 'createPets',
+                    'tags': [
+                        'pets'
+                    ],
+                    'responses': {
+                        '201': {
+                            'description': 'Null response'
+                        },
+                        'default': {
+                            'description': 'unexpected error',
+                            'content': {
+                                'application/json': {
+// TO BE FOUND
+                                    'schema': {
+                                        'required': [
+                                            'code',
+                                            'message'
+                                        ],
+                                        'properties': {
+                                            'code': {
+                                                'type': 'number'
+                                            },
+                                            'message': {
+                                                'type': 'string'
+                                            }
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            },
+            '/pets/{petId}': {
+                'get': {
+                    'summary': 'Info for a specific pet',
+                    'operationId': 'showPetById',
+                    'parameters': [
+                        {
+                            'name': 'petId',
+                            'in': 'path',
+                            'required': true,
+                            'description': 'The id of the pet to retrieve',
+                            'schema': {
+                                'type': 'string'
+                            }
+                        }
+                    ],
+                    'responses': {
+                        '200': {
+                            'description': 'Expected response to a valid request',
+                            'content': {
+                                'application/json': {
+// TO BE FOUND
+                                    'schema': {
+                                        'required': [
+                                            'id',
+                                            'name'
+                                        ],
+                                        'properties': {
+                                            'id': {
+                                                'type': 'number'
+                                            },
+                                            'name': {
+                                                'type': 'string'
+                                            },
+                                            'tag': {
+                                                'type': 'string'
+                                            },
+// TO BE FOUND
+                                            'schema': {
+                                                'type': 'object',
+                                                'properties': {
+// TO BE FOUND
+                                                    'properties': {
+                                                        'type': 'object',
+                                                        'properties': {
+                                                            'color': {
+                                                                'type': 'string'
+                                                            }
+                                                        }
+                                                    }
+                                                }
+                                            }
+                                        }
+                                    },
+                                    'example': {
+                                        'id': 0,
+                                        'name': 'Herbert',
+                                        'tag': 'Doggo',
+                                        'owner': 'John',
+                                        'age': 5,
+// NOT TO BE FOUND
+                                        'schema': {
+                                            'properties': {
+                                                'color': 'black'
+                                            }
+                                        }
+                                    }
+                                }
+                            }
+                        },
+                        'default': {
+                            'description': 'unexpected error',
+                            'content': {
+                                'application/json': {
+// TO BE FOUND
+                                    'schema': {
+                                        'required': [
+                                            'code',
+                                            'message'
+                                        ],
+                                        'properties': {
+                                            'code': {
+                                                'type': 'number'
+                                            },
+                                            'message': {
+                                                'type': 'string'
+                                            }
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    };
+}
+
+function _getPaths() {
+    /* eslint-disable max-len */
+    return [
+        "$['paths']['/pets']['get']['responses'][200]['content']['application/json']['schema']",
+        "$['paths']['/pets']['get']['responses'][200]['content']['application/json']['schema']['items']",
+        "$['paths']['/pets']['get']['responses'][200]['content']['application/json']['schema']['items']['properties']['schema']",
+        "$['paths']['/pets']['get']['responses'][200]['content']['application/json']['schema']['items']['properties']['schema']['properties']['properties']",
+        "$['paths']['/pets']['get']['responses'][200]['content']['application/json']['schema']['items']['properties']['schema']['properties']['properties']['properties']['properties']",
+        "$['paths']['/pets']['get']['responses']['default']['content']['application/json']['schema']",
+        "$['paths']['/pets']['post']['responses']['default']['content']['application/json']['schema']",
+        "$['paths']['/pets/{petId}']['get']['responses'][200]['content']['application/json']['schema']",
+        "$['paths']['/pets/{petId}']['get']['responses'][200]['content']['application/json']['schema']['properties']['schema']",
+        "$['paths']['/pets/{petId}']['get']['responses'][200]['content']['application/json']['schema']['properties']['schema']['properties']['properties']",
+        "$['paths']['/pets/{petId}']['get']['responses']['default']['content']['application/json']['schema']"
+    ];
+    /* eslint-enable max-len */
+}
diff --git a/test/specs/impl/v2/index.js b/test/specs/impl/v2/index.js
index 6e1ec6e..36bcca2 100644
--- a/test/specs/impl/v2/index.js
+++ b/test/specs/impl/v2/index.js
@@ -25,27 +25,27 @@ const PATH__SCHEMA_EXTERNAL_EXAMPLE = '$.paths./.get.responses.200.schema',
 
 describe('Main-module, for v2 should', () => {
     describe('recognize', () => {
-        it('valid single example', () => {
-            validateExamples(loadTestData('v2/valid-single-example')).valid.should.equal(true);
+        it('valid single example', async() => {
+            (await validateExamples(loadTestData('v2/valid-single-example'))).valid.should.equal(true);
         });
-        it('valid multiple examples', () => {
-            validateExamples(loadTestData('v2/valid-multiple-examples')).valid.should.equal(true);
+        it('valid multiple examples', async() => {
+            (await validateExamples(loadTestData('v2/valid-multiple-examples'))).valid.should.equal(true);
         });
-        it('valid array-example', () => {
-            validateExamples(loadTestData('v2/valid-array-response')).valid.should.equal(true);
+        it('valid array-example', async() => {
+            (await validateExamples(loadTestData('v2/valid-array-response'))).valid.should.equal(true);
         });
     });
     describe('ignore', () => {
-        it('responses without schema', () => {
-            validateExamples(loadTestData('v2/valid-without-schema')).valid.should.equal(true);
+        it('responses without schema', async() => {
+            (await validateExamples(loadTestData('v2/valid-without-schema'))).valid.should.equal(true);
         });
-        it('responses without examples', () => {
-            validateExamples(loadTestData('v2/valid-without-examples')).valid.should.equal(true);
+        it('responses without examples', async() => {
+            (await validateExamples(loadTestData('v2/valid-without-examples'))).valid.should.equal(true);
         });
     });
     describe('find error:', () => {
-        it('invalid type', () => {
-            const result = validateExamples(loadTestData('v2/invalid-type'));
+        it('invalid type', async() => {
+            const result = await validateExamples(loadTestData('v2/invalid-type'));
             result.valid.should.equal(false);
             result.errors.should.deep.equal([new ApplicationError(ErrorType.validation, {
                 dataPath: '.versions[0].id',
@@ -58,8 +58,8 @@ describe('Main-module, for v2 should', () => {
                 examplePath: '/paths/~1/get/responses/200/examples/application~1json'
             })]);
         });
-        it('multiple errors', () => {
-            const result = validateExamples(loadTestData('v2/multiple-errors'));
+        it('multiple errors', async() => {
+            const result = await validateExamples(loadTestData('v2/multiple-errors'));
             result.valid.should.equal(false);
             result.errors.should.deep.equal([
                 new ApplicationError(ErrorType.validation, {
@@ -95,8 +95,8 @@ describe('Main-module, for v2 should', () => {
             ]);
         });
         describe('In array-response:', () => {
-            it('multiple errors', () => {
-                const result = validateExamples(loadTestData('v2/invalid-array-response'));
+            it('multiple errors', async() => {
+                const result = await validateExamples(loadTestData('v2/invalid-array-response'));
                 result.valid.should.equal(false);
                 result.errors.should.deep.equal([
                     new ApplicationError(ErrorType.validation, {
diff --git a/test/specs/impl/v3/index.js b/test/specs/impl/v3/index.js
index ba6e081..ad84fd1 100644
--- a/test/specs/impl/v3/index.js
+++ b/test/specs/impl/v3/index.js
@@ -1,17 +1,39 @@
 const path = require('path'),
+    fs = require('fs'),
+    yaml = require('yaml'),
     { loadTestData } = require('../../../util/setup-tests'),
     { ErrorType } = require('../../../../src/application-error'),
-    { 'default': validateExamples, validateFile } = require('../../../../src/index');
+    { 'default': validateExamples, validateFile, validateExample, validateExamplesByMap }
+        = require('../../../../src/index'),
+    errorsAdditionalProperties
+        = require('../../../data/v3/additional-properties/errors-schema-with-examples.json'),
+    errorsAdditionalPropertiesList
+        = require('../../../data/v3/additional-properties/errors-list.json'),
+    errorsAdditionalPropertiesMap
+        = require('../../../data/v3/additional-properties/errors-map-external-examples.json'),
+    errorsAdditionalPropertiesSingle
+        = require('../../../data/v3/additional-properties/errors-single.json');
 
 const JSON_PATH__CONTEXT_MUTUALLY_EXCLUSIVE = '/paths/~1pets/get/responses/200/content/application~1json',
     REL_PATH__EXAMPLE__SIMPLE = 'v3/simple-api-with-example',
+    REL_PATH__EXAMPLE__INVALID__WITH_INTERNAL_REFS = 'v3/simple-api-with-example-with-refs-invalid',
     REL_PATH__EXAMPLE_AND_EXAMPLES__SIMPLE = 'v3/simple-api-with-example-and-examples',
     REL_PATH__EXAMPLES__SIMPLE = 'v3/simple-api-with-examples',
     REL_PATH__WITH_INTERNAL_REFS = 'v3/simple-api-with-examples-with-refs',
-    REL_PATH__EXAMPLE__INVALID__WITH_INTERNAL_REFS = 'v3/simple-api-with-example-with-refs-invalid',
     REL_PATH__EXAMPLES__INVALID__WITH_INTERNAL_REFS = 'v3/simple-api-with-examples-with-refs-invalid',
+    FILE_PATH__EXAMPLE__WITH_ADDITIONAL_PROPERTIES__LIST
+        = path.join(__dirname, '../../../data/v3/additional-properties/example-list-with-additional-properties.json'),
+    FILE_PATH__EXAMPLE__WITH_ADDITIONAL_PROPERTIES__SINGLE
+        = path.join(__dirname, '../../../data/v3/additional-properties/example-single-with-additional-properties.json'),
     FILE_PATH__EXAMPLES_WITH_MISSING_SCHEMA
         = path.join(__dirname, '../../../data/v3/simple-api-with-examples-and-missing-schema.json'),
+    FILE_PATH__MAP__WITH_ADDITIONAL_PROPERTIES = path.join(__dirname,
+        '../../../data/v3/additional-properties/map-external-examples-with-additional-properties.json'
+    ),
+    FILE_PATH__SCHEMA__WITH_ADDITIONAL_PROPERTIES
+        = path.join(__dirname, '../../../data/v3/additional-properties/schema.yaml'),
+    FILE_PATH__SCHEMA__WITH_ADDITIONAL_PROPERTIES_WITH_EXAMPLES
+        = path.join(__dirname, '../../../data/v3/additional-properties/schema-with-examples.yaml'),
     FILE_PATH__INVALID__YAML = path.join(__dirname, '../../../data/v3/simple-api-with-examples-with-refs-invalid.yaml'),
     FILE_PATH__INVALID__INDENTATION__YAML
         = path.join(__dirname, '../../../data/v3/simple-api-with-examples-invalid-indentation.yml'),
@@ -41,15 +63,15 @@ const JSON_PATH__CONTEXT_MUTUALLY_EXCLUSIVE = '/paths/~1pets/get/responses/200/c
 describe('Main-module, for v3 should', function() {
     describe('recognize', function() {
         describe('`example`-property', function() {
-            it('valid single example', function() {
-                validateExamples(loadTestData(REL_PATH__EXAMPLE__SIMPLE)).valid.should.equal(true);
+            it('valid single example', async function() {
+                (await validateExamples(loadTestData(REL_PATH__EXAMPLE__SIMPLE))).valid.should.equal(true);
             });
-            it('invalid example with internal refs', function() {
-                validateExamples(loadTestData(REL_PATH__EXAMPLE__INVALID__WITH_INTERNAL_REFS))
+            it('invalid example with internal refs', async function() {
+                (await validateExamples(loadTestData(REL_PATH__EXAMPLE__INVALID__WITH_INTERNAL_REFS)))
                     .valid.should.equal(false);
             });
-            it('throw error, if example and examples are defined', function() {
-                const validationResult = validateExamples(loadTestData(REL_PATH__EXAMPLE_AND_EXAMPLES__SIMPLE)),
+            it('throw error, if example and examples are defined', async function() {
+                const validationResult = await validateExamples(loadTestData(REL_PATH__EXAMPLE_AND_EXAMPLES__SIMPLE)),
                     error = validationResult.errors[0];
                 validationResult.valid.should.equal(false);
                 validationResult.errors.length.should.equal(1);
@@ -59,22 +81,22 @@ describe('Main-module, for v3 should', function() {
             });
         });
         describe('`examples`-property', function() {
-            it('statistics for multiple examples', function() {
-                const { statistics } = validateExamples(loadTestData(REL_PATH__EXAMPLES__SIMPLE));
+            it('statistics for multiple examples', async function() {
+                const { statistics } = await validateExamples(loadTestData(REL_PATH__EXAMPLES__SIMPLE));
                 statistics.should.deep.equal({
                     examplesTotal: 3,
                     examplesWithoutSchema: 0,
                     schemasWithExamples: 1
                 });
             });
-            it('valid examples', function() {
-                validateExamples(loadTestData(REL_PATH__EXAMPLES__SIMPLE)).valid.should.equal(true);
+            it('valid examples', async function() {
+                (await validateExamples(loadTestData(REL_PATH__EXAMPLES__SIMPLE))).valid.should.equal(true);
             });
-            it('example with internal refs', function() {
-                validateExamples(loadTestData(REL_PATH__WITH_INTERNAL_REFS)).valid.should.equal(true);
+            it('example with internal refs', async function() {
+                (await validateExamples(loadTestData(REL_PATH__WITH_INTERNAL_REFS))).valid.should.equal(true);
             });
-            it('invalid example with internal refs', function() {
-                validateExamples(loadTestData(REL_PATH__EXAMPLES__INVALID__WITH_INTERNAL_REFS))
+            it('invalid example with internal refs', async function() {
+                (await validateExamples(loadTestData(REL_PATH__EXAMPLES__INVALID__WITH_INTERNAL_REFS)))
                     .valid.should.equal(false);
             });
         });
@@ -257,4 +279,83 @@ describe('Main-module, for v3 should', function() {
                 .statistics.schemasWithExamples.should.equal(2);
         });
     });
+    describe('with additional properties', function() {
+        describe('with flag not set', function() {
+            it('`validateFile` should not show any error', async function() {
+                (await validateFile(FILE_PATH__SCHEMA__WITH_ADDITIONAL_PROPERTIES_WITH_EXAMPLES))
+                    .valid.should.equal(true);
+            });
+            it('`validateExamples` should not show any error', async function() {
+                (await validateExamples(
+                    yaml.parse(fs.readFileSync(FILE_PATH__SCHEMA__WITH_ADDITIONAL_PROPERTIES_WITH_EXAMPLES, 'utf-8'))
+                )).valid.should.equal(true);
+            });
+            it('`validateExample` should not show any error', async function() {
+                (await validateExample(
+                    FILE_PATH__SCHEMA__WITH_ADDITIONAL_PROPERTIES,
+                    '$.paths./pets.get.responses.200.content.application/json.schema',
+                    FILE_PATH__EXAMPLE__WITH_ADDITIONAL_PROPERTIES__LIST
+                )).valid.should.equal(true);
+            });
+            it('`validateExample` should not show any error', async function() {
+                (await validateExample(
+                    FILE_PATH__SCHEMA__WITH_ADDITIONAL_PROPERTIES,
+                    '$.paths./pets/{petId}.get.responses.200.content.application/json.schema',
+                    FILE_PATH__EXAMPLE__WITH_ADDITIONAL_PROPERTIES__SINGLE
+                )).valid.should.equal(true);
+            });
+            it('`validateExamplesByMap` should not show any error', async function() {
+                (await validateExamplesByMap(
+                    FILE_PATH__SCHEMA__WITH_ADDITIONAL_PROPERTIES,
+                    FILE_PATH__MAP__WITH_ADDITIONAL_PROPERTIES
+                )).valid.should.equal(true);
+            });
+        });
+        describe('with flag set', function() {
+            it('`validateFile` should throw an error', async function() {
+                (await validateFile(
+                    FILE_PATH__SCHEMA__WITH_ADDITIONAL_PROPERTIES_WITH_EXAMPLES,
+                    { noAdditionalProperties: true }
+                )).errors.should.deep.equal(errorsAdditionalProperties);
+            });
+            it('`validateExamples` should throw an error', async function() {
+                (await validateExamples(
+                    yaml.parse(fs.readFileSync(FILE_PATH__SCHEMA__WITH_ADDITIONAL_PROPERTIES_WITH_EXAMPLES, 'utf-8')),
+                    { noAdditionalProperties: true }
+                )).errors.should.deep.equal(errorsAdditionalProperties);
+            });
+            it('`validateExample` for a list should throw an error', async function() {
+                (await validateExample(
+                    FILE_PATH__SCHEMA__WITH_ADDITIONAL_PROPERTIES,
+                    '$.paths./pets.get.responses.200.content.application/json.schema',
+                    FILE_PATH__EXAMPLE__WITH_ADDITIONAL_PROPERTIES__LIST,
+                    { noAdditionalProperties: true }
+                )).errors.should.deep.equal(_expandFilePathOfErrors(errorsAdditionalPropertiesList, 'exampleFilePath'));
+            });
+            it('`validateExample` for a single example should throw an error', async function() {
+                (await validateExample(
+                    FILE_PATH__SCHEMA__WITH_ADDITIONAL_PROPERTIES,
+                    '$.paths./pets/{petId}.get.responses.200.content.application/json.schema',
+                    FILE_PATH__EXAMPLE__WITH_ADDITIONAL_PROPERTIES__SINGLE,
+                    { noAdditionalProperties: true }
+                )).errors.should.deep.equal(
+                    _expandFilePathOfErrors(errorsAdditionalPropertiesSingle, 'exampleFilePath')
+                );
+            });
+            it('`validateExamplesByMap` should throw an error', async function() {
+                (await validateExamplesByMap(
+                    FILE_PATH__SCHEMA__WITH_ADDITIONAL_PROPERTIES,
+                    FILE_PATH__MAP__WITH_ADDITIONAL_PROPERTIES,
+                    { noAdditionalProperties: true }
+                )).errors.should.deep.equal(_expandFilePathOfErrors(errorsAdditionalPropertiesMap, 'mapFilePath'));
+            });
+        });
+    });
 });
+
+function _expandFilePathOfErrors(errors, propertyName) {
+    errors.forEach(error => {
+        error[propertyName] = path.join(__dirname, '../../../..', error[propertyName]);
+    });
+    return errors;
+}
diff --git a/test/specs/index.js b/test/specs/index.js
index 2e368b0..0464b75 100644
--- a/test/specs/index.js
+++ b/test/specs/index.js
@@ -25,8 +25,8 @@ const PATH__SCHEMA_EXTERNAL_EXAMPLE = '$.paths./.get.responses.200.schema',
 describe('Main API', function() {
     describe('validateExamples', function() {
         describe('API version 2', function() {
-            it('should successfully validate the file', function() {
-                validateExamples(loadTestData('v2/valid-single-example')).valid.should.equal(true);
+            it('should successfully validate the file', async function() {
+                (await validateExamples(loadTestData('v2/valid-single-example'))).valid.should.equal(true);
             });
         });
     });