Skip to content

Commit

Permalink
Merge pull request #3245 from wing328/security_fix_javascript
Browse files Browse the repository at this point in the history
[Javascript] better code injection handling for Javascript API client
  • Loading branch information
wing328 committed Jun 29, 2016
2 parents acc2849 + 8e43f7c commit 90857e8
Show file tree
Hide file tree
Showing 119 changed files with 3,932 additions and 243 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ samples/server-generator/scalatra/target
samples/server-generator/scalatra/output/.history

# nodejs
**/node_modules/
**/node_modules
samples/server-generator/node/output/node_modules
samples/server/petstore/nodejs/node_modules
samples/server/petstore/nodejs-server/node_modules
Expand Down
31 changes: 31 additions & 0 deletions bin/security/javascript-petstore.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#!/bin/sh

SCRIPT="$0"

while [ -h "$SCRIPT" ] ; do
ls=`ls -ld "$SCRIPT"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
SCRIPT="$link"
else
SCRIPT=`dirname "$SCRIPT"`/"$link"
fi
done

if [ ! -d "${APP_DIR}" ]; then
APP_DIR=`dirname "$SCRIPT"`/..
APP_DIR=`cd "${APP_DIR}"; pwd`
fi

executable="./modules/swagger-codegen-cli/target/swagger-codegen-cli.jar"

if [ ! -f "$executable" ]
then
mvn clean package
fi

# if you've executed sbt assembly previously it will use that instead.
export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties"
ags="$@ generate -t modules/swagger-codegen/src/main/resources/Javascript -i modules/swagger-codegen/src/test/resources/2_0/petstore-security-test.yaml -l javascript -o samples/client/petstore-security-test/javascript"

java -DappName=PetstoreClient $JAVA_OPTS -jar $executable $ags
Original file line number Diff line number Diff line change
Expand Up @@ -240,21 +240,21 @@ public void preprocessSwagger(Swagger swagger) {
Info info = swagger.getInfo();
if (StringUtils.isBlank(projectName) && info.getTitle() != null) {
// when projectName is not specified, generate it from info.title
projectName = dashize(info.getTitle());
projectName = sanitizeName(dashize(info.getTitle()));
}
if (StringUtils.isBlank(projectVersion)) {
// when projectVersion is not specified, use info.version
projectVersion = info.getVersion();
projectVersion = escapeUnsafeCharacters(escapeQuotationMark(info.getVersion()));
}
if (projectDescription == null) {
// when projectDescription is not specified, use info.description
projectDescription = info.getDescription();
projectDescription = sanitizeName(info.getDescription());
}
if (additionalProperties.get(PROJECT_LICENSE_NAME) == null) {
// when projectLicense is not specified, use info.license
if (info.getLicense() != null) {
License license = info.getLicense();
additionalProperties.put(PROJECT_LICENSE_NAME, license.getName());
additionalProperties.put(PROJECT_LICENSE_NAME, sanitizeName(license.getName()));
}
}
}
Expand Down Expand Up @@ -1032,4 +1032,16 @@ public String toEnumValue(String value, String datatype) {
}
}


@Override
public String escapeQuotationMark(String input) {
// remove ', " to avoid code injection
return input.replace("\"", "").replace("'", "");
}

@Override
public String escapeUnsafeCharacters(String input) {
return input.replace("*/", "");
}

}
30 changes: 15 additions & 15 deletions modules/swagger-codegen/src/main/resources/Javascript/api.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -2,41 +2,41 @@
{{=< >=}}(function(root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(['<#invokerPackage><invokerPackage>/</invokerPackage>ApiClient'<#imports>, '<#invokerPackage><invokerPackage>/</invokerPackage><#modelPackage><modelPackage>/</modelPackage><import>'</imports>], factory);
define(['<#invokerPackage><&invokerPackage>/</invokerPackage>ApiClient'<#imports>, '<#invokerPackage><&invokerPackage>/</invokerPackage><#modelPackage><&modelPackage>/</modelPackage><import>'</imports>], factory);
} else if (typeof module === 'object' && module.exports) {
// CommonJS-like environments that support module.exports, like Node.
module.exports = factory(require('../ApiClient')<#imports>, require('../<#modelPackage><modelPackage>/</modelPackage><import>')</imports>);
module.exports = factory(require('../ApiClient')<#imports>, require('../<#modelPackage><&modelPackage>/</modelPackage><import>')</imports>);
} else {
// Browser globals (root is window)
if (!root.<moduleName>) {
root.<moduleName> = {};
if (!root.<&moduleName>) {
root.<&moduleName> = {};
}
root.<moduleName>.<classname> = factory(root.<moduleName>.ApiClient<#imports>, root.<moduleName>.<import></imports>);
root.<&moduleName>.<&classname> = factory(root.<&moduleName>.ApiClient<#imports>, root.<&moduleName>.<import></imports>);
}
}(this, function(ApiClient<#imports>, <import></imports>) {
'use strict';
<#emitJSDoc> /**
* <baseName> service.
* @module <#invokerPackage><invokerPackage>/</invokerPackage><#apiPackage><apiPackage>/</apiPackage><classname>
* @module <#invokerPackage><&invokerPackage>/</invokerPackage><#apiPackage><&apiPackage>/</apiPackage><classname>
* @version <projectVersion>
*/
/**
* Constructs a new <classname>. <#description>
* Constructs a new <&classname>. <#description>
* <description></description>
* @alias module:<#invokerPackage><invokerPackage>/</invokerPackage><#apiPackage><apiPackage>/</apiPackage><classname>
* @alias module:<#invokerPackage><&invokerPackage>/</invokerPackage><#apiPackage><apiPackage>/</apiPackage><classname>
* @class
* @param {module:<#invokerPackage><invokerPackage>/</invokerPackage>ApiClient} apiClient Optional API client implementation to use,
* default to {@link module:<#invokerPackage><invokerPackage>/</invokerPackage>ApiClient#instance} if unspecified.
* @param {module:<#invokerPackage><&invokerPackage>/</invokerPackage>ApiClient} apiClient Optional API client implementation to use,
* default to {@link module:<#invokerPackage><&invokerPackage>/</invokerPackage>ApiClient#instance} if unspecified.
*/
</emitJSDoc> var exports = function(apiClient) {
this.apiClient = apiClient || ApiClient.instance;
<#operations><#operation><#emitJSDoc><^usePromises>
/**
* Callback function to receive the result of the <nickname> operation.
* @callback module:<#invokerPackage><invokerPackage>/</invokerPackage><#apiPackage><apiPackage>/</apiPackage><classname>~<nickname>Callback
* Callback function to receive the result of the <operationId> operation.
* @callback module:<#invokerPackage><invokerPackage>/</invokerPackage><#apiPackage><apiPackage>/</apiPackage><classname>~<operationId>Callback
* @param {String} error Error message, if any.
* @param <#vendorExtensions.x-jsdoc-type><&vendorExtensions.x-jsdoc-type> data The data returned by the service call.</vendorExtensions.x-jsdoc-type><^vendorExtensions.x-jsdoc-type>data This operation does not return a value.</vendorExtensions.x-jsdoc-type>
* @param {String} response The complete HTTP response.
Expand All @@ -48,16 +48,16 @@
* @param <&vendorExtensions.x-jsdoc-type> <paramName> <description></required></allParams><#hasOptionalParams>
* @param {Object} opts Optional parameters<#allParams><^required>
* @param <&vendorExtensions.x-jsdoc-type> opts.<paramName> <description><#defaultValue> (default to <.>)</defaultValue></required></allParams></hasOptionalParams><^usePromises>
* @param {module:<#invokerPackage><invokerPackage>/</invokerPackage><#apiPackage><apiPackage>/</apiPackage><classname>~<nickname>Callback} callback The callback function, accepting three arguments: error, data, response</usePromises><#returnType>
* @param {module:<#invokerPackage><&invokerPackage>/</invokerPackage><#apiPackage><&apiPackage>/</apiPackage><&classname>~<operationId>Callback} callback The callback function, accepting three arguments: error, data, response</usePromises><#returnType>
* data is of type: <&vendorExtensions.x-jsdoc-type></returnType>
*/
</emitJSDoc> this.<nickname> = function(<vendorExtensions.x-codegen-argList>) {<#hasOptionalParams>
</emitJSDoc> this.<operationId> = function(<vendorExtensions.x-codegen-argList>) {<#hasOptionalParams>
opts = opts || {};</hasOptionalParams>
var postBody = <#bodyParam><#required><paramName></required><^required>opts['<paramName>']</required></bodyParam><^bodyParam>null</bodyParam>;
<#allParams><#required>
// verify the required parameter '<paramName>' is set
if (<paramName> == undefined || <paramName> == null) {
throw "Missing the required parameter '<paramName>' when calling <nickname>";
throw "Missing the required parameter '<paramName>' when calling <operationId>";
}
</required></allParams>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,20 @@ exports.prototype['{{baseName}}'] = {{#defaultValue}}{{{defaultValue}}}{{/defaul
}

{{/vars}}{{/emitModelMethods}}
{{#vars}}{{#isEnum}}{{>partial_model_inner_enum}}{{/isEnum}}{{#items.isEnum}}{{#items}}
{{>partial_model_inner_enum}}{{/items}}*/{{/items.isEnum}}{{/vars}}
{{#vars}}
{{#isEnum}}
{{^isContainer}}
{{>partial_model_inner_enum}}
{{/isContainer}}
{{/isEnum}}
{{#items.isEnum}}
{{#items}}
{{^isContainer}}
{{>partial_model_inner_enum}}
{{/isContainer}}
{{/items}}
{{/items.isEnum}}
{{/vars}}

return exports;
{{/model}}{{/models}}}));
Original file line number Diff line number Diff line change
Expand Up @@ -1101,13 +1101,15 @@ definitions:
type: array
items:
$ref: '#/definitions/ReadOnlyFirst'
array_of_enum:
type: array
items:
type: string
enum:
- UPPER
- lower
# commented out the below test case for array of enum for the time being
# as not all language can handle it
#array_of_enum:
# type: array
# items:
# type: string
# enum:
# - UPPER
# - lower
NumberOnly:
type: object
properties:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Swagger Codegen Ignore
# Generated by swagger-codegen https://github.com/swagger-api/swagger-codegen

# Use this file to prevent files from being overwritten by the generator.
# The patterns follow closely to .gitignore or .dockerignore.

# As an example, the C# client generator defines ApiClient.cs.
# You can make changes and tell Swagger Codgen to ignore just this file by uncommenting the following line:
#ApiClient.cs

# You can match any string of characters against a directory, file or extension with a single asterisk (*):
#foo/*/qux
# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux

# You can recursively match patterns against a directory, file or extension with a double asterisk (**):
#foo/**/qux
# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux

# You can also negate patterns with an exclamation (!).
# For example, you can ignore all files in a docs folder with the file extension .md:
#docs/*.md
# Then explicitly reverse the ignore rule for a single file:
#!docs/README.md
7 changes: 7 additions & 0 deletions samples/client/petstore-security-test/javascript/.travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
language: node_js
node_js:
- "6"
- "6.1"
- "5"
- "5.11"

Loading

0 comments on commit 90857e8

Please sign in to comment.