@contrast/agent 4.7.0 → 4.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/agent-loader.js +1 -1
- package/bin/VERSION +1 -1
- package/bin/linux/contrast-service +0 -0
- package/bin/mac/contrast-service +0 -0
- package/bin/windows/contrast-service.exe +0 -0
- package/bootstrap.js +13 -3
- package/cli-rewriter.js +1 -1
- package/cli.js +1 -1
- package/esm.mjs +34 -1
- package/lib/agent-emitter.js +1 -1
- package/lib/agent.js +1 -1
- package/lib/app-info.js +1 -1
- package/lib/assess/deadzones/index.js +1 -1
- package/lib/assess/deadzones/rewrite.js +1 -1
- package/lib/assess/express/index.js +1 -1
- package/lib/assess/express/route-coverage.js +1 -1
- package/lib/assess/express/sinks/index.js +1 -1
- package/lib/assess/express/sinks/xss.js +1 -1
- package/lib/assess/express/sources.js +1 -1
- package/lib/assess/fastify/index.js +1 -1
- package/lib/assess/fastify/route-coverage.js +1 -1
- package/lib/assess/fastify/sinks/index.js +1 -1
- package/lib/assess/fastify/sinks/response-scanning.js +1 -1
- package/lib/assess/fastify/sinks/unvalidated-redirect.js +1 -1
- package/lib/assess/fastify/sinks/xss.js +1 -1
- package/lib/assess/fastify/sources.js +1 -1
- package/lib/assess/hapi/index.js +1 -1
- package/lib/assess/hapi/route-coverage.js +1 -1
- package/lib/assess/hapi/sinks/index.js +1 -1
- package/lib/assess/hapi/sinks/response-scanning.js +1 -1
- package/lib/assess/hapi/sinks/session.js +1 -1
- package/lib/assess/hapi/sinks/unvalidated-redirect.js +1 -1
- package/lib/assess/hapi/sinks/xss.js +1 -1
- package/lib/assess/hapi/sources.js +1 -1
- package/lib/assess/index.js +3 -1
- package/lib/assess/koa/index.js +1 -1
- package/lib/assess/koa/route-coverage.js +1 -1
- package/lib/assess/koa/sinks/index.js +1 -1
- package/lib/assess/koa/sinks/response-scanning.js +1 -1
- package/lib/assess/koa/sinks/unvalidated-redirect.js +1 -1
- package/lib/assess/koa/sinks/xss.js +1 -1
- package/lib/assess/koa/sources.js +1 -1
- package/lib/assess/loopback4/index.js +1 -1
- package/lib/assess/loopback4/route-coverage.js +1 -1
- package/lib/assess/loopback4/sinks/index.js +1 -1
- package/lib/assess/loopback4/sinks/response-scanning.js +1 -1
- package/lib/assess/loopback4/sinks/xss.js +1 -1
- package/lib/assess/loopback4/sources.js +1 -1
- package/lib/assess/membrane/debraner.js +1 -1
- package/lib/assess/membrane/deserialization-membrane.js +5 -6
- package/lib/assess/membrane/index.js +1 -1
- package/lib/assess/membrane/source-membrane.js +16 -20
- package/lib/assess/models/base-event.js +1 -1
- package/lib/assess/models/call-context.js +2 -2
- package/lib/assess/models/index.js +1 -1
- package/lib/assess/models/propagation-event.js +1 -1
- package/lib/assess/models/signature.js +1 -1
- package/lib/assess/models/sink-event.js +1 -1
- package/lib/assess/models/source-event.js +7 -1
- package/lib/assess/models/tag-range/index.js +1 -1
- package/lib/assess/models/tag-range/relationships.js +1 -1
- package/lib/assess/models/tag-range/util.js +1 -1
- package/lib/assess/policy/index.js +1 -1
- package/lib/assess/policy/init.js +1 -1
- package/lib/assess/policy/propagators.json +8 -0
- package/lib/assess/policy/rules.json +31 -2
- package/lib/assess/policy/signatures.json +33 -6
- package/lib/assess/policy/util.js +3 -2
- package/lib/assess/propagators/JSON/parse.js +2 -2
- package/lib/assess/propagators/JSON/stringify.js +81 -11
- package/lib/assess/propagators/ajv/conditionals.js +1 -1
- package/lib/assess/propagators/ajv/evaluator-shim.js +1 -1
- package/lib/assess/propagators/ajv/index.js +1 -1
- package/lib/assess/propagators/ajv/json-schema-type-evaluators.js +1 -1
- package/lib/assess/propagators/ajv/object-walk.js +1 -1
- package/lib/assess/propagators/ajv/refs.js +1 -1
- package/lib/assess/propagators/ajv/schema-context.js +1 -1
- package/lib/assess/propagators/array-prototype-join.js +8 -9
- package/lib/assess/propagators/common.js +8 -6
- package/lib/assess/propagators/dustjs/escape-html.js +1 -1
- package/lib/assess/propagators/dustjs/escape-js.js +1 -1
- package/lib/assess/propagators/ejs-template-generate-source.js +1 -1
- package/lib/assess/propagators/encode-uri/encode-uri-component.js +1 -1
- package/lib/assess/propagators/encode-uri/encode-uri.js +1 -1
- package/lib/assess/propagators/handlebars-compile.js +1 -1
- package/lib/assess/propagators/handlebars-escape-expresssion.js +2 -2
- package/lib/assess/propagators/index.js +1 -1
- package/lib/assess/propagators/joi/boolean.js +2 -2
- package/lib/assess/propagators/joi/expression.js +2 -2
- package/lib/assess/propagators/joi/index.js +1 -1
- package/lib/assess/propagators/joi/number.js +2 -2
- package/lib/assess/propagators/joi/string-base.js +2 -2
- package/lib/assess/propagators/joi/string-schema.js +13 -14
- package/lib/assess/propagators/joi/values.js +12 -12
- package/lib/assess/propagators/manager.js +13 -11
- package/lib/assess/propagators/mongoose/helpers.js +20 -0
- package/lib/assess/propagators/mongoose/index.js +18 -0
- package/lib/assess/propagators/mongoose/map.js +74 -0
- package/lib/assess/propagators/mongoose/string.js +104 -0
- package/lib/assess/propagators/mustache/escape.js +1 -1
- package/lib/assess/propagators/number.js +54 -0
- package/lib/assess/propagators/object.js +7 -8
- package/lib/assess/propagators/path/basename.js +15 -14
- package/lib/assess/propagators/path/common.js +2 -2
- package/lib/assess/propagators/path/dirname.js +15 -14
- package/lib/assess/propagators/path/extname.js +15 -14
- package/lib/assess/propagators/path/format.js +1 -1
- package/lib/assess/propagators/path/join.js +1 -1
- package/lib/assess/propagators/path/normalize.js +1 -1
- package/lib/assess/propagators/path/parse.js +2 -2
- package/lib/assess/propagators/path/relative.js +8 -6
- package/lib/assess/propagators/path/resolve.js +1 -1
- package/lib/assess/propagators/path/to-namespaced-path.js +1 -1
- package/lib/assess/propagators/pug-compile.js +1 -1
- package/lib/assess/propagators/querystring/escape.js +21 -19
- package/lib/assess/propagators/querystring/parse.js +8 -6
- package/lib/assess/propagators/querystring/stringify.js +26 -25
- package/lib/assess/propagators/querystring/unescape.js +21 -19
- package/lib/assess/propagators/querystring/utils.js +1 -1
- package/lib/assess/propagators/sequelize/sql-string-escape.js +2 -2
- package/lib/assess/propagators/sequelize/sql-string-format-named-parameters.js +2 -2
- package/lib/assess/propagators/sequelize/sql-string-format.js +4 -4
- package/lib/assess/propagators/sequelize/utils.js +3 -3
- package/lib/assess/propagators/string-prototype-replace.js +31 -29
- package/lib/assess/propagators/string-prototype-split.js +37 -37
- package/lib/assess/propagators/string-prototype-trim.js +16 -18
- package/lib/assess/propagators/string.js +13 -17
- package/lib/assess/propagators/template-escape.js +22 -19
- package/lib/assess/propagators/templates.js +9 -9
- package/lib/assess/propagators/url/url-prototype-parse.js +6 -7
- package/lib/assess/propagators/url/url-url.js +52 -44
- package/lib/assess/propagators/url/utils.js +1 -1
- package/lib/assess/propagators/util/format.js +2 -2
- package/lib/assess/propagators/utils.js +1 -1
- package/lib/assess/propagators/v8/init-hooks.js +4 -4
- package/lib/assess/propagators/validator/init-hooks.js +23 -23
- package/lib/assess/propagators/validator/validator-methods.js +1 -2
- package/lib/assess/response-scanning/app-activity.js +1 -1
- package/lib/assess/response-scanning/autocomplete-missing.js +1 -1
- package/lib/assess/response-scanning/cache-controls-missing.js +1 -1
- package/lib/assess/response-scanning/clickjacking-control-missing.js +1 -1
- package/lib/assess/response-scanning/common.js +1 -1
- package/lib/assess/response-scanning/cookies/common.js +1 -1
- package/lib/assess/response-scanning/cookies/events.js +1 -1
- package/lib/assess/response-scanning/cookies/httponly.js +1 -1
- package/lib/assess/response-scanning/cookies/secure-flag-missing.js +1 -1
- package/lib/assess/response-scanning/headers/csp-header-insecure.js +1 -1
- package/lib/assess/response-scanning/headers/csp-header-missing.js +1 -1
- package/lib/assess/response-scanning/headers/csp-utils.js +1 -1
- package/lib/assess/response-scanning/headers/hsts-header-missing.js +1 -1
- package/lib/assess/response-scanning/headers/powered-by.js +1 -1
- package/lib/assess/response-scanning/headers/xcontenttype-header-missing.js +1 -1
- package/lib/assess/response-scanning/headers/xxssprotection-header-disabled.js +1 -1
- package/lib/assess/response-scanning/parameter-pollution.js +1 -1
- package/lib/assess/response-scanning/parseable-response-emitter.js +1 -1
- package/lib/assess/restify/index.js +1 -1
- package/lib/assess/restify/route-coverage.js +1 -1
- package/lib/assess/restify/session.js +1 -1
- package/lib/assess/restify/sinks/index.js +1 -1
- package/lib/assess/restify/sinks/response-scanning.js +1 -1
- package/lib/assess/restify/sinks/unvalidated-redirect.js +1 -1
- package/lib/assess/restify/sinks/xss.js +1 -1
- package/lib/assess/restify/sources.js +1 -1
- package/lib/assess/sinks/common.js +11 -6
- package/lib/assess/sinks/dustjs-linkedin-xss.js +1 -1
- package/lib/assess/sinks/dynamo.js +1 -1
- package/lib/assess/sinks/hapi-16-xss.js +1 -1
- package/lib/assess/sinks/index.js +1 -1
- package/lib/assess/sinks/libxmljs-xxe.js +2 -2
- package/lib/assess/sinks/mongodb.js +3 -2
- package/lib/assess/sinks/rethinkdb-nosql-injection.js +142 -0
- package/lib/assess/sinks/ssrf-url.js +2 -2
- package/lib/assess/sources/event-handler.js +307 -0
- package/lib/assess/sources/formidable.js +1 -1
- package/lib/assess/sources/index.js +94 -6
- package/lib/assess/spdy/index.js +23 -0
- package/lib/assess/spdy/sinks/index.js +23 -0
- package/lib/assess/spdy/sinks/xss.js +84 -0
- package/lib/assess/static/hardcoded.js +1 -1
- package/lib/assess/technologies/index.js +3 -2
- package/lib/assess/utils.js +1 -1
- package/lib/cli-rewriter/index.js +1 -1
- package/lib/constants.js +7 -3
- package/lib/contrast.js +7 -7
- package/lib/core/arch-components/dynamodb.js +1 -1
- package/lib/core/arch-components/dynamodbv3.js +1 -1
- package/lib/core/arch-components/index.js +2 -1
- package/lib/core/arch-components/mongodb.js +23 -19
- package/lib/core/arch-components/mysql.js +1 -1
- package/lib/core/arch-components/postgres.js +22 -4
- package/lib/core/arch-components/rethinkdb.js +1 -1
- package/lib/core/arch-components/sqlite3.js +4 -6
- package/lib/core/async-storage/context.js +1 -1
- package/lib/core/async-storage/hooks/bluebird.js +1 -1
- package/lib/core/async-storage/hooks/mongodb-core.js +1 -1
- package/lib/core/async-storage/hooks/mysql.js +1 -1
- package/lib/core/async-storage/hooks/redis.js +1 -1
- package/lib/core/async-storage/hooks/utils.js +1 -1
- package/lib/core/async-storage/index.js +1 -1
- package/lib/core/async-storage/scopes/index.js +1 -1
- package/lib/core/common/formidable.js +1 -1
- package/lib/core/common/index.js +1 -1
- package/lib/core/config/options.js +37 -3
- package/lib/core/config/util.js +1 -1
- package/lib/core/exclusions/exclusion-factory.js +1 -1
- package/lib/core/exclusions/exclusion.js +3 -6
- package/lib/core/exclusions/input.js +1 -1
- package/lib/core/exclusions/url.js +1 -1
- package/lib/core/express/index.js +26 -3
- package/lib/core/express/utils.js +9 -4
- package/lib/core/fastify/index.js +1 -1
- package/lib/core/fastify/utils.js +1 -1
- package/lib/core/hapi/index.js +1 -1
- package/lib/core/hapi/utils.js +1 -1
- package/lib/core/index.js +1 -1
- package/lib/core/koa/index.js +1 -1
- package/lib/core/koa/utils.js +1 -1
- package/lib/core/logger/daily-rotate-file.js +1 -1
- package/lib/core/logger/dataflow-monitor.js +1 -1
- package/lib/core/logger/debug-logger.js +1 -1
- package/lib/core/logger/index.js +1 -1
- package/lib/core/logger/perf-logger.js +1 -1
- package/lib/core/logger/umbrella-logger.js +1 -1
- package/lib/core/loopback4/index.js +1 -1
- package/lib/core/metrics/index.js +1 -1
- package/lib/core/restify/index.js +1 -1
- package/lib/core/restify/utils.js +1 -1
- package/lib/core/rewrite/assignment-expression.js +1 -1
- package/lib/core/rewrite/binary-expression.js +1 -1
- package/lib/core/rewrite/call-expression.js +1 -1
- package/lib/core/rewrite/callees.js +1 -1
- package/lib/core/rewrite/catch-clause.js +1 -1
- package/lib/core/rewrite/function-wrap.js +1 -1
- package/lib/core/rewrite/index.js +1 -1
- package/lib/core/rewrite/injections.js +9 -1
- package/lib/core/rewrite/is-contrast-method.js +1 -1
- package/lib/core/rewrite/log.js +1 -1
- package/lib/core/rewrite/member-expression.js +1 -1
- package/lib/core/rewrite/object-property.js +1 -1
- package/lib/core/rewrite/prepend-globals.js +1 -1
- package/lib/core/rewrite/rewrite-log.js +1 -1
- package/lib/core/rewrite/switch-statement.js +1 -1
- package/lib/core/rewrite/template-literal.js +1 -1
- package/lib/core/stacktrace.js +1 -1
- package/lib/coverage.js +1 -1
- package/lib/feature-set.js +2 -2
- package/lib/generator-function.js +1 -1
- package/lib/hooks/array.js +1 -1
- package/lib/hooks/cluster.js +1 -1
- package/lib/hooks/dataflow-monitor.js +1 -1
- package/lib/hooks/encoding.js +1 -1
- package/lib/hooks/express-fileupload.js +1 -1
- package/lib/hooks/express-session.js +1 -1
- package/lib/hooks/fn-to-string.js +1 -1
- package/lib/hooks/frameworks/base.js +1 -1
- package/lib/hooks/frameworks/common.js +1 -1
- package/lib/hooks/frameworks/hapi16.js +1 -1
- package/lib/hooks/frameworks/http.js +1 -1
- package/lib/hooks/frameworks/http2.js +1 -1
- package/lib/hooks/frameworks/index.js +3 -1
- package/lib/hooks/frameworks/spdy.js +87 -0
- package/lib/hooks/hapi-16-reply.js +1 -1
- package/lib/hooks/hapi-16-session.js +1 -1
- package/lib/hooks/http.js +12 -1
- package/lib/hooks/module/extensions.js +1 -1
- package/lib/hooks/module/helpers.js +1 -1
- package/lib/hooks/module/index.js +1 -1
- package/lib/hooks/newrelic.js +1 -1
- package/lib/hooks/object-is.js +1 -1
- package/lib/hooks/object-to-primitive.js +7 -8
- package/lib/hooks/patcher.js +2 -2
- package/lib/hooks/require.js +1 -1
- package/lib/hooks/stealthy-require.js +1 -1
- package/lib/instrumentation.js +1 -1
- package/lib/libraries.js +1 -1
- package/lib/library-usage.js +1 -1
- package/lib/list-installed.js +1 -1
- package/lib/protect/analysis/aho-corasick.js +1 -1
- package/lib/protect/analysis/dfsa-analyzer.js +1 -1
- package/lib/protect/errors/handler.js +1 -1
- package/lib/protect/errors/security-exception.js +1 -1
- package/lib/protect/express/index.js +1 -1
- package/lib/protect/express/sinks.js +1 -1
- package/lib/protect/express/sources.js +1 -1
- package/lib/protect/fastify/index.js +1 -1
- package/lib/protect/fastify/sinks.js +1 -1
- package/lib/protect/fastify/sources.js +1 -1
- package/lib/protect/hapi/error-handler.js +1 -1
- package/lib/protect/hapi/index.js +1 -1
- package/lib/protect/hapi/sinks.js +1 -1
- package/lib/protect/hapi/sources.js +1 -1
- package/lib/protect/index.js +1 -1
- package/lib/protect/input-analysis.js +1 -1
- package/lib/protect/koa/index.js +1 -1
- package/lib/protect/koa/sinks.js +1 -1
- package/lib/protect/koa/sources.js +1 -1
- package/lib/protect/listeners.js +1 -1
- package/lib/protect/loopback4/index.js +1 -1
- package/lib/protect/loopback4/sources.js +1 -1
- package/lib/protect/models/application-context.js +1 -1
- package/lib/protect/models/sink-event.js +1 -1
- package/lib/protect/models/source-event.js +1 -1
- package/lib/protect/restify/index.js +1 -1
- package/lib/protect/restify/sinks.js +1 -1
- package/lib/protect/restify/sources.js +1 -1
- package/lib/protect/rules/assessment.js +1 -1
- package/lib/protect/rules/attack-patterns.js +1 -1
- package/lib/protect/rules/base-scanner/index.js +1 -1
- package/lib/protect/rules/base-scanner/java-script-scanner.js +1 -1
- package/lib/protect/rules/base-scanner/postgresqlscanner.js +1 -1
- package/lib/protect/rules/base-scanner/scan-state.js +1 -1
- package/lib/protect/rules/base-scanner/substring-finder.js +1 -1
- package/lib/protect/rules/base-scanner/token-sequence.js +1 -1
- package/lib/protect/rules/bot-blocker/bot-blocker-rule.js +1 -1
- package/lib/protect/rules/bot-blocker/index.js +1 -1
- package/lib/protect/rules/cmd-injection/cmdinjection-rule.js +1 -1
- package/lib/protect/rules/cmd-injection-command-backdoors/backdoor-detector.js +1 -1
- package/lib/protect/rules/cmd-injection-command-backdoors/cmd-injection-command-backdoors-rule.js +1 -1
- package/lib/protect/rules/cmd-injection-semantic-chained-commands/chained-command-scanner.js +1 -1
- package/lib/protect/rules/cmd-injection-semantic-chained-commands/cmd-injection-semantic-chained-commands-rule.js +1 -1
- package/lib/protect/rules/cmd-injection-semantic-dangerous-paths/cmd-injection-semantic-dangerous-paths-rule.js +1 -1
- package/lib/protect/rules/cmd-injection-semantic-dangerous-paths/dangerous-paths-scanner.js +1 -1
- package/lib/protect/rules/common.js +1 -1
- package/lib/protect/rules/index.js +1 -1
- package/lib/protect/rules/ip-denylist/ip-denylist-rule.js +1 -1
- package/lib/protect/rules/method-tampering/evaluator.js +1 -1
- package/lib/protect/rules/method-tampering/method-tampering-rule.js +1 -1
- package/lib/protect/rules/nosqli/nosql-injection-rule.js +228 -0
- package/lib/protect/rules/nosqli/nosql-scanner/index.js +1 -1
- package/lib/protect/rules/nosqli/nosql-scanner/mongodbscanner.js +1 -1
- package/lib/protect/rules/path-traversal/path-traversal-rule.js +1 -1
- package/lib/protect/rules/rule-factory.js +3 -3
- package/lib/protect/rules/signatures/cmd-injection/custom-searchers/chained-command-searcher.js +1 -1
- package/lib/protect/rules/signatures/cmd-injection/custom-searchers/index.js +1 -1
- package/lib/protect/rules/signatures/cmd-injection/index.js +1 -1
- package/lib/protect/rules/signatures/evaluator.js +1 -1
- package/lib/protect/rules/signatures/index.js +1 -1
- package/lib/protect/rules/signatures/nosql-injection/custom-searchers/index.js +1 -1
- package/lib/protect/rules/signatures/nosql-injection/custom-searchers/nosql-comment-searcher.js +1 -1
- package/lib/protect/rules/signatures/nosql-injection/custom-searchers/simple-or-searcher.js +1 -1
- package/lib/protect/rules/signatures/nosql-injection/index.js +1 -1
- package/lib/protect/rules/signatures/path-traversal/index.js +1 -1
- package/lib/protect/rules/signatures/reflected-xss/custom-searchers/behavior-url-searcher.js +1 -1
- package/lib/protect/rules/signatures/reflected-xss/custom-searchers/function-definition-searcher.js +1 -1
- package/lib/protect/rules/signatures/reflected-xss/custom-searchers/immediate-function-searcher.js +1 -1
- package/lib/protect/rules/signatures/reflected-xss/custom-searchers/index.js +1 -1
- package/lib/protect/rules/signatures/reflected-xss/custom-searchers/link-and-src-target-searcher.js +1 -1
- package/lib/protect/rules/signatures/reflected-xss/custom-searchers/location-set-searcher.js +1 -1
- package/lib/protect/rules/signatures/reflected-xss/custom-searchers/map-access-searcher.js +1 -1
- package/lib/protect/rules/signatures/reflected-xss/custom-searchers/native-function-execution-searcher.js +1 -1
- package/lib/protect/rules/signatures/reflected-xss/custom-searchers/no-alnum-searcher.js +1 -1
- package/lib/protect/rules/signatures/reflected-xss/custom-searchers/redefined-function-searcher.js +1 -1
- package/lib/protect/rules/signatures/reflected-xss/custom-searchers/style-url-injection-searcher.js +1 -1
- package/lib/protect/rules/signatures/reflected-xss/custom-searchers/variable-assignment-searcher.js +1 -1
- package/lib/protect/rules/signatures/reflected-xss/helpers/function-call.js +1 -1
- package/lib/protect/rules/signatures/reflected-xss/index.js +1 -1
- package/lib/protect/rules/signatures/signature.js +1 -1
- package/lib/protect/rules/signatures/sql-injection/custom-searchers/if-else-drop-searcher.js +1 -1
- package/lib/protect/rules/signatures/sql-injection/custom-searchers/index.js +1 -1
- package/lib/protect/rules/signatures/sql-injection/custom-searchers/simple-or-searcher.js +1 -1
- package/lib/protect/rules/signatures/sql-injection/custom-searchers/sql-comment-searcher.js +1 -1
- package/lib/protect/rules/signatures/sql-injection/custom-searchers/time-function-searcher.js +1 -1
- package/lib/protect/rules/signatures/sql-injection/custom-searchers/tsql-exec-searcher.js +1 -1
- package/lib/protect/rules/signatures/sql-injection/index.js +1 -1
- package/lib/protect/rules/signatures/ssjs-injection/index.js +1 -1
- package/lib/protect/rules/signatures/unsafe-file-upload/index.js +1 -1
- package/lib/protect/rules/signatures/untrusted-deserialization/index.js +1 -1
- package/lib/protect/rules/sqli/generic-complicated.js +1 -1
- package/lib/protect/rules/sqli/sql-injection-rule.js +1 -1
- package/lib/protect/rules/sqli/sql-scanner/index.js +1 -1
- package/lib/protect/rules/sqli/sql-scanner/mysql-scanner.js +1 -1
- package/lib/protect/rules/ssjs-injection/evaluator.js +1 -1
- package/lib/protect/rules/ssjs-injection/ssjsinjection-rule.js +1 -1
- package/lib/protect/rules/unsafe-file-upload/unsafe-file-upload-rule.js +1 -1
- package/lib/protect/rules/untrusted-deserialization/untrusted-deserialization-rule.js +1 -1
- package/lib/protect/rules/virtual-patch/index.js +1 -1
- package/lib/protect/rules/virtual-patch/utils.js +1 -1
- package/lib/protect/rules/virtual-patch/virtual-patch-rule.js +1 -1
- package/lib/protect/rules/xss/helpers/function-call.js +1 -1
- package/lib/protect/rules/xss/reflected-xss-rule.js +1 -1
- package/lib/protect/rules/xxe/xxerule.js +1 -1
- package/lib/protect/sample-aggregator.js +1 -1
- package/lib/protect/samples.js +1 -1
- package/lib/protect/service.js +24 -12
- package/lib/protect/sinks/child-process.js +1 -1
- package/lib/protect/sinks/eval.js +1 -1
- package/lib/protect/sinks/fs.js +1 -1
- package/lib/protect/sinks/function.js +1 -1
- package/lib/protect/sinks/index.js +1 -1
- package/lib/protect/sinks/libxmljs.js +1 -1
- package/lib/protect/sinks/mongodb.js +57 -56
- package/lib/protect/sinks/mysql.js +1 -1
- package/lib/protect/sinks/node-serialize.js +1 -1
- package/lib/protect/sinks/postgres.js +1 -1
- package/lib/protect/sinks/sequelize.js +1 -1
- package/lib/protect/sinks/sqlite3.js +1 -1
- package/lib/protect/sinks/vm.js +1 -1
- package/lib/protect/sources/busboy.js +1 -1
- package/lib/protect/sources/formidable.js +1 -1
- package/lib/protect/sources/index.js +1 -1
- package/lib/protect/validators/authorization.js +1 -1
- package/lib/protect/validators/common.js +1 -1
- package/lib/protect/validators/connection.js +1 -1
- package/lib/protect/validators/content-length.js +1 -1
- package/lib/protect/validators/host.js +1 -1
- package/lib/protect/validators/if-none-match.js +1 -1
- package/lib/protect/validators/index.js +1 -1
- package/lib/protect/validators/origin.js +1 -1
- package/lib/reporter/app-activity-queue.js +1 -1
- package/lib/reporter/grpc-client.js +1 -1
- package/lib/reporter/messages/speedracer/activity.js +1 -1
- package/lib/reporter/messages/speedracer/application-create.js +1 -1
- package/lib/reporter/messages/speedracer/application-update.js +1 -1
- package/lib/reporter/messages/speedracer/base.js +1 -1
- package/lib/reporter/messages/speedracer/index.js +1 -1
- package/lib/reporter/messages/speedracer/observed-route.js +1 -1
- package/lib/reporter/messages/speedracer/poll.js +1 -1
- package/lib/reporter/messages/speedracer/request.js +1 -1
- package/lib/reporter/messages/speedracer/startup.js +1 -1
- package/lib/reporter/messaging-router.js +1 -1
- package/lib/reporter/models/app-activity/app-activity.js +1 -1
- package/lib/reporter/models/app-activity/attacker-activity.js +1 -1
- package/lib/reporter/models/app-activity/defend.js +1 -1
- package/lib/reporter/models/app-activity/inventory.js +1 -1
- package/lib/reporter/models/app-activity/protection-rule-activity.js +1 -1
- package/lib/reporter/models/app-activity/rule-events.js +1 -1
- package/lib/reporter/models/app-activity/sample.js +1 -1
- package/lib/reporter/models/app-activity/source.js +1 -1
- package/lib/reporter/models/app-activity/user-input.js +1 -1
- package/lib/reporter/models/app-create.js +1 -1
- package/lib/reporter/models/app-update/index.js +1 -1
- package/lib/reporter/models/app-update/library-manifest.js +1 -1
- package/lib/reporter/models/app-update/library-usage.js +1 -1
- package/lib/reporter/models/app-update/library.js +1 -1
- package/lib/reporter/models/event-tag.js +1 -1
- package/lib/reporter/models/finding/event.js +1 -1
- package/lib/reporter/models/finding/finding.js +1 -1
- package/lib/reporter/models/frameworks/express-request.js +1 -1
- package/lib/reporter/models/frameworks/fastify-request.js +1 -1
- package/lib/reporter/models/frameworks/hapi-request.js +1 -1
- package/lib/reporter/models/frameworks/index.js +1 -1
- package/lib/reporter/models/frameworks/koa-request.js +1 -1
- package/lib/reporter/models/frameworks/restify-request.js +1 -1
- package/lib/reporter/models/observed-route.js +1 -1
- package/lib/reporter/models/request.js +1 -1
- package/lib/reporter/models/route-coverage.js +1 -1
- package/lib/reporter/models/startup.js +1 -1
- package/lib/reporter/models/trace-event-source.js +1 -1
- package/lib/reporter/models/utils/request-factory.js +1 -1
- package/lib/reporter/models/utils/user-input-factory.js +1 -1
- package/lib/reporter/models/utils/user-input-kit.js +1 -1
- package/lib/reporter/mq-client.js +1 -1
- package/lib/reporter/server-activity-queue.js +1 -1
- package/lib/reporter/socket-client.js +1 -1
- package/lib/reporter/speedracer/base-connection-state.js +1 -1
- package/lib/reporter/speedracer/constants.js +1 -1
- package/lib/reporter/speedracer/failure-connection-state.js +1 -1
- package/lib/reporter/speedracer/index.js +1 -1
- package/lib/reporter/speedracer/success-connection-state.js +1 -1
- package/lib/reporter/speedracer/unknown-connection-state.js +1 -1
- package/lib/reporter/translations/enums.js +1 -1
- package/lib/reporter/translations/helpers.js +1 -1
- package/lib/reporter/translations/to-protobuf/dtm/activity.js +1 -1
- package/lib/reporter/translations/to-protobuf/dtm/address.js +1 -1
- package/lib/reporter/translations/to-protobuf/dtm/agent-startup.js +1 -1
- package/lib/reporter/translations/to-protobuf/dtm/application-create.js +1 -1
- package/lib/reporter/translations/to-protobuf/dtm/application-update.js +1 -1
- package/lib/reporter/translations/to-protobuf/dtm/architecture-component.js +1 -1
- package/lib/reporter/translations/to-protobuf/dtm/attack-result.js +1 -1
- package/lib/reporter/translations/to-protobuf/dtm/bot-blocker-details.js +1 -1
- package/lib/reporter/translations/to-protobuf/dtm/cmd-injection-details.js +1 -1
- package/lib/reporter/translations/to-protobuf/dtm/cmd-injection-semantic-analysis-details.js +1 -1
- package/lib/reporter/translations/to-protobuf/dtm/finding.js +1 -1
- package/lib/reporter/translations/to-protobuf/dtm/http-method-tampering-details.js +1 -1
- package/lib/reporter/translations/to-protobuf/dtm/http-request.js +1 -1
- package/lib/reporter/translations/to-protobuf/dtm/index.js +2 -2
- package/lib/reporter/translations/to-protobuf/dtm/ip-denylist-details.js +2 -2
- package/lib/reporter/translations/to-protobuf/dtm/library-usage-update.js +1 -1
- package/lib/reporter/translations/to-protobuf/dtm/no-sql-injection-details.js +1 -1
- package/lib/reporter/translations/to-protobuf/dtm/observed-route.js +1 -1
- package/lib/reporter/translations/to-protobuf/dtm/pair.js +1 -1
- package/lib/reporter/translations/to-protobuf/dtm/path-traversal-details.js +1 -1
- package/lib/reporter/translations/to-protobuf/dtm/poll.js +1 -1
- package/lib/reporter/translations/to-protobuf/dtm/rasp-rule-sample.js +2 -2
- package/lib/reporter/translations/to-protobuf/dtm/raw-request.js +1 -1
- package/lib/reporter/translations/to-protobuf/dtm/route-coverage.js +1 -1
- package/lib/reporter/translations/to-protobuf/dtm/simple-pair.js +1 -1
- package/lib/reporter/translations/to-protobuf/dtm/sql-injection-details.js +1 -1
- package/lib/reporter/translations/to-protobuf/dtm/ssjs-injection-details.js +1 -1
- package/lib/reporter/translations/to-protobuf/dtm/stack-trace-element.js +1 -1
- package/lib/reporter/translations/to-protobuf/dtm/trace-event/action.js +1 -1
- package/lib/reporter/translations/to-protobuf/dtm/trace-event/index.js +5 -5
- package/lib/reporter/translations/to-protobuf/dtm/trace-event/parent-object-id.js +1 -1
- package/lib/reporter/translations/to-protobuf/dtm/trace-event/trace-event-object.js +1 -1
- package/lib/reporter/translations/to-protobuf/dtm/trace-event/trace-event-signature.js +1 -1
- package/lib/reporter/translations/to-protobuf/dtm/trace-event/trace-event-source.js +1 -1
- package/lib/reporter/translations/to-protobuf/dtm/trace-event/trace-stack.js +1 -1
- package/lib/reporter/translations/to-protobuf/dtm/trace-event/trace-taint-range.js +1 -1
- package/lib/reporter/translations/to-protobuf/dtm/trace-event/type.js +1 -1
- package/lib/reporter/translations/to-protobuf/dtm/untrusted-deserialization-details.js +1 -1
- package/lib/reporter/translations/to-protobuf/dtm/user-input.js +1 -1
- package/lib/reporter/translations/to-protobuf/dtm/virtual-patch-details.js +1 -1
- package/lib/reporter/translations/to-protobuf/dtm/xss-details.js +1 -1
- package/lib/reporter/translations/to-protobuf/dtm/xxe-details.js +1 -1
- package/lib/reporter/translations/to-protobuf/index.js +1 -1
- package/lib/reporter/translations/to-protobuf/settings/application-settings.js +1 -1
- package/lib/reporter/translations/to-protobuf/settings/assess-features.js +1 -1
- package/lib/reporter/translations/to-protobuf/settings/auth.js +1 -1
- package/lib/reporter/translations/to-protobuf/settings/bot-blocker.js +1 -1
- package/lib/reporter/translations/to-protobuf/settings/custom-rule-feature.js +1 -1
- package/lib/reporter/translations/to-protobuf/settings/defend-features.js +9 -7
- package/lib/reporter/translations/to-protobuf/settings/exclusions.js +6 -5
- package/lib/reporter/translations/to-protobuf/settings/index.js +1 -1
- package/lib/reporter/translations/to-protobuf/settings/input-analysis-result.js +1 -1
- package/lib/reporter/translations/to-protobuf/settings/inventory-features.js +1 -1
- package/lib/reporter/translations/to-protobuf/settings/ip-filter.js +1 -1
- package/lib/reporter/translations/to-protobuf/settings/log-enhancer.js +1 -1
- package/lib/reporter/translations/to-protobuf/settings/protection-rule.js +1 -1
- package/lib/reporter/translations/to-protobuf/settings/reaction.js +1 -1
- package/lib/reporter/translations/to-protobuf/settings/rule-definition.js +1 -1
- package/lib/reporter/translations/to-protobuf/settings/sampling.js +1 -1
- package/lib/reporter/translations/to-protobuf/settings/server-features.js +1 -1
- package/lib/reporter/translations/to-protobuf/settings/syslog.js +1 -1
- package/lib/reporter/translations/to-protobuf/settings/virtual-patch.js +1 -1
- package/lib/reporter/ts-reporter.js +1 -1
- package/lib/tracker.js +14 -66
- package/lib/util/base64.js +1 -1
- package/lib/util/bitset.js +1 -1
- package/lib/util/block-request.js +1 -1
- package/lib/util/callback-resolver.js +1 -1
- package/lib/util/clean-stack.js +1 -1
- package/lib/util/clean-string/brackets.js +1 -1
- package/lib/util/clean-string/clean-string-base.js +1 -1
- package/lib/util/clean-string/comments.js +1 -1
- package/lib/util/clean-string/concatenations.js +1 -1
- package/lib/util/clean-string/jsclean-string.js +1 -1
- package/lib/util/clean-string/placeholders.js +1 -1
- package/lib/util/clean-string/util.js +1 -1
- package/lib/util/colors.js +1 -1
- package/lib/util/file-finder.js +1 -1
- package/lib/util/heap-dump.js +1 -1
- package/lib/util/html-util.js +1 -1
- package/lib/util/ip-analyzer.js +1 -1
- package/lib/util/is-agent-path.js +1 -1
- package/lib/util/is-contrast-error.js +1 -1
- package/lib/util/is-piped-to-dev.js +1 -1
- package/lib/util/is-string.js +1 -1
- package/lib/util/partial.js +1 -1
- package/lib/util/pkg-name.js +1 -1
- package/lib/util/request-util.js +1 -1
- package/lib/util/resolve-obj.js +1 -1
- package/lib/util/route-info.js +1 -1
- package/lib/util/some.js +1 -1
- package/lib/util/source-map.js +4 -4
- package/lib/util/static-rules.js +1 -1
- package/lib/util/trace-util.js +1 -1
- package/lib/util/traverse.js +1 -1
- package/lib/util/user-input-evaluator.js +1 -1
- package/lib/util/xml-analyzer/external-entity-finder.js +1 -1
- package/package.json +7 -6
- package/perf-logs.js +1 -1
- package/lib/protect/rules/nosqli/no-sql-injection-rule.js +0 -109
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
/**
|
|
2
|
+
Copyright: 2022 Contrast Security, Inc
|
|
3
|
+
Contact: support@contrastsecurity.com
|
|
4
|
+
License: Commercial
|
|
5
|
+
|
|
6
|
+
NOTICE: This Software and the patented inventions embodied within may only be
|
|
7
|
+
used as part of Contrast Security’s commercial offerings. Even though it is
|
|
8
|
+
made available through public repositories, use of this Software is subject to
|
|
9
|
+
the applicable End User Licensing Agreement found at
|
|
10
|
+
https://www.contrastsecurity.com/enduser-terms-0317a or as otherwise agreed
|
|
11
|
+
between Contrast Security and the End User. The Software may not be reverse
|
|
12
|
+
engineered, modified, repackaged, sold, redistributed or otherwise used in a
|
|
13
|
+
way not consistent with the End User License Agreement.
|
|
14
|
+
*/
|
|
15
|
+
'use strict';
|
|
16
|
+
|
|
17
|
+
const logger = require('../../core/logger')('contrast:assess.sources');
|
|
18
|
+
const { PATCH_TYPES } = require('../../constants');
|
|
19
|
+
const { CallContext, SourceEvent } = require('../models');
|
|
20
|
+
const TraceEventSource = require('../../reporter/models/trace-event-source');
|
|
21
|
+
const { AsyncStorage, KEYS } = require('../../core/async-storage');
|
|
22
|
+
const TagRange = require('../models/tag-range');
|
|
23
|
+
const patcher = require('../../hooks/patcher');
|
|
24
|
+
const tracker = require('../../tracker');
|
|
25
|
+
const parseurl = require('parseurl');
|
|
26
|
+
|
|
27
|
+
const SOURCE_EVENT_MAX = 250;
|
|
28
|
+
const trackedObjects = new WeakMap();
|
|
29
|
+
|
|
30
|
+
class SourceEventHandler {
|
|
31
|
+
constructor({
|
|
32
|
+
config = {
|
|
33
|
+
agent: {
|
|
34
|
+
node: {
|
|
35
|
+
array_request_sampling: {
|
|
36
|
+
enable: true,
|
|
37
|
+
threshold: 50,
|
|
38
|
+
interval: 5
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
ensureReq = true,
|
|
44
|
+
exclusions,
|
|
45
|
+
stackOpts,
|
|
46
|
+
snapshot,
|
|
47
|
+
signature,
|
|
48
|
+
type = 'UNKNOWN'
|
|
49
|
+
} = {}) {
|
|
50
|
+
this.config = config;
|
|
51
|
+
this.exclusions = exclusions;
|
|
52
|
+
this.type = type;
|
|
53
|
+
this.snapshot = snapshot;
|
|
54
|
+
this.signature = signature;
|
|
55
|
+
this.stackOpts = stackOpts;
|
|
56
|
+
this.ensureReq = ensureReq;
|
|
57
|
+
this.samplingEnabled = config.agent.node.array_request_sampling.enable;
|
|
58
|
+
this.samplingThreshold = config.agent.node.array_request_sampling.threshold;
|
|
59
|
+
this.samplingInterval = this.samplingEnabled
|
|
60
|
+
? config.agent.node.array_request_sampling.interval
|
|
61
|
+
: 1;
|
|
62
|
+
|
|
63
|
+
this.inputExclusions = [];
|
|
64
|
+
this.urlExclusions = [];
|
|
65
|
+
this.skipEvent = false;
|
|
66
|
+
this.sourceEventCount = 0;
|
|
67
|
+
|
|
68
|
+
this.init();
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
init() {
|
|
72
|
+
// values reused in functions
|
|
73
|
+
this.req = AsyncStorage.get(KEYS.REQ);
|
|
74
|
+
|
|
75
|
+
// NODE-1431: prevents crashing when req is not present in AsyncStorage.
|
|
76
|
+
if (!this.req) {
|
|
77
|
+
if (!this.ensureReq) return;
|
|
78
|
+
|
|
79
|
+
this.skipEvent = true;
|
|
80
|
+
logger.debug(
|
|
81
|
+
'failed to handle source event for type: %s; request not present in async storage',
|
|
82
|
+
this.type
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (!this.exclusions) return;
|
|
87
|
+
|
|
88
|
+
const { pathname } = parseurl(this.req);
|
|
89
|
+
|
|
90
|
+
this.inputExclusions = this.exclusions
|
|
91
|
+
.getInputExclusions('assess')
|
|
92
|
+
.reduce((acc, e) => {
|
|
93
|
+
if (!e.matchesUrl(pathname)) return acc;
|
|
94
|
+
|
|
95
|
+
// `isNamed` is false for exclusion types such as BODY and QUERYSTRING which
|
|
96
|
+
// apply to the entire set of params not only those by a specified name. Also
|
|
97
|
+
// is true if the input name is set to wildcard "*" meaning it should apply to
|
|
98
|
+
// all values. In each case there's no need to wrap if all rules are excluded.
|
|
99
|
+
if (!this.skipEvent && e.appliesToAllAssessRules() && !e.isNamed) {
|
|
100
|
+
logExclusionMessage(e, this.type);
|
|
101
|
+
this.skipEvent = true;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
acc.push(e);
|
|
105
|
+
return acc;
|
|
106
|
+
}, []);
|
|
107
|
+
|
|
108
|
+
this.urlExclusions = this.exclusions
|
|
109
|
+
.getUrlExclusions('assess')
|
|
110
|
+
.reduce((acc, e) => {
|
|
111
|
+
if (!e.matchesUrl(pathname)) return acc;
|
|
112
|
+
|
|
113
|
+
if (!this.skipEvent && e.appliesToAllAssessRules()) {
|
|
114
|
+
logExclusionMessage(e, this.type);
|
|
115
|
+
this.skipEvent = true;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
acc.push(e);
|
|
119
|
+
return acc;
|
|
120
|
+
}, []);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
*
|
|
125
|
+
* @param {object} param
|
|
126
|
+
* @param {object} param.obj usually the incoming message
|
|
127
|
+
* @param {string} param.prop obj[prop] is containing user-controlled data
|
|
128
|
+
*/
|
|
129
|
+
handle({ obj, prop }) {
|
|
130
|
+
this.typeKey = prop;
|
|
131
|
+
|
|
132
|
+
if (this.skipEvent) return;
|
|
133
|
+
|
|
134
|
+
this.traverseAndTrack({ obj, key: prop });
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// eslint-disable-next-line complexity
|
|
138
|
+
traverseAndTrack({ obj, key, path = [] }) {
|
|
139
|
+
const value = obj[key];
|
|
140
|
+
|
|
141
|
+
if (!value) return;
|
|
142
|
+
|
|
143
|
+
if (this.sourceEventCount > SOURCE_EVENT_MAX) {
|
|
144
|
+
logger.debug('max sources exceeded for %s', this.type);
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
if (Array.isArray(value)) {
|
|
149
|
+
const limit = Math.min(value.length, this.samplingThreshold);
|
|
150
|
+
|
|
151
|
+
trackedObjects.set(value, { ...this, path, key });
|
|
152
|
+
|
|
153
|
+
for (let i = 0; i < limit; i += this.samplingInterval) {
|
|
154
|
+
this.traverseAndTrack({
|
|
155
|
+
obj: value,
|
|
156
|
+
key: i,
|
|
157
|
+
path: [...path, i]
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
} else if (Buffer.isBuffer(value)) {
|
|
161
|
+
this.sourceEventCount++;
|
|
162
|
+
patcher.patch(value, 'toString', {
|
|
163
|
+
name: 'Buffer.toString',
|
|
164
|
+
alwaysRun: true,
|
|
165
|
+
patchType: PATCH_TYPES.MISC,
|
|
166
|
+
post: (wrapCtx) => {
|
|
167
|
+
this.trackStringProp({
|
|
168
|
+
obj: wrapCtx,
|
|
169
|
+
key: 'result',
|
|
170
|
+
path
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
} else if (typeof value === 'string' || value instanceof String) {
|
|
175
|
+
this.sourceEventCount++;
|
|
176
|
+
this.trackStringProp({ obj, key, path });
|
|
177
|
+
} else if (typeof value === 'object') {
|
|
178
|
+
trackedObjects.set(value, { ...this, path, key });
|
|
179
|
+
|
|
180
|
+
for (const objKey of Object.keys(value)) {
|
|
181
|
+
this.traverseAndTrack({
|
|
182
|
+
obj: value,
|
|
183
|
+
path: [...path, objKey],
|
|
184
|
+
key: objKey
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
trackStringProp({ obj, key, path, value = obj[key] }) {
|
|
191
|
+
const trackData = tracker.track(value);
|
|
192
|
+
if (!trackData) {
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
const name = path.join('.');
|
|
197
|
+
const { props, str: result } = trackData;
|
|
198
|
+
|
|
199
|
+
props.tagRanges = this.getTagRanges({ name, result });
|
|
200
|
+
props.event = new SourceEvent({
|
|
201
|
+
context: new CallContext({
|
|
202
|
+
obj: 'IncomingMessage {}',
|
|
203
|
+
args: [`${this.typeKey}.${name}`],
|
|
204
|
+
result,
|
|
205
|
+
stackOpts: this.stackOpts
|
|
206
|
+
}),
|
|
207
|
+
code: `req.${this.typeKey}.${name}`,
|
|
208
|
+
signature: this.signature,
|
|
209
|
+
tagRanges: props.tagRanges,
|
|
210
|
+
target: 'R',
|
|
211
|
+
type: this.type,
|
|
212
|
+
name
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
// NOTE: this used to happen on access in SourceMembrane.onString(), though we
|
|
216
|
+
// should be able to determine access of source value during dataflow - when a
|
|
217
|
+
// source is tracked into PROPAGATION or SINK event.
|
|
218
|
+
storeSource({ type: this.type, name: key });
|
|
219
|
+
|
|
220
|
+
obj[key] = result;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
getTagRanges({ result, name }) {
|
|
224
|
+
const stop = result.length - 1;
|
|
225
|
+
const tagRanges = [new TagRange(0, stop, 'untrusted')];
|
|
226
|
+
|
|
227
|
+
const typeLowerCase = this.type.toLowerCase();
|
|
228
|
+
const nameLowerCase = name.toLocaleLowerCase();
|
|
229
|
+
|
|
230
|
+
if (typeLowerCase === 'header' && nameLowerCase !== 'referer') {
|
|
231
|
+
tagRanges.push(new TagRange(0, stop, 'header'));
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
if (typeLowerCase === 'cookie') {
|
|
235
|
+
tagRanges.push(new TagRange(0, stop, 'cookie'));
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
if (!this.inputExclusions.length) {
|
|
239
|
+
return tagRanges;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
const rules = new Set();
|
|
243
|
+
|
|
244
|
+
/*
|
|
245
|
+
Maybe it's pointless because we set skipEvent to true if appliesToAllAssessRules
|
|
246
|
+
and we won't get here
|
|
247
|
+
*/
|
|
248
|
+
const exclusions = this.inputExclusions.filter(
|
|
249
|
+
(e) => !e.appliesToAllAssessRules()
|
|
250
|
+
);
|
|
251
|
+
|
|
252
|
+
for (const exclusion of exclusions) {
|
|
253
|
+
if (!exclusion.matches(name)) {
|
|
254
|
+
continue;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
for (const ruleId of exclusion.assessmentRulesList) {
|
|
258
|
+
logger.debug(
|
|
259
|
+
'excluding %s %s value from %s (%s)',
|
|
260
|
+
this.type,
|
|
261
|
+
name,
|
|
262
|
+
ruleId,
|
|
263
|
+
exclusion.name
|
|
264
|
+
);
|
|
265
|
+
|
|
266
|
+
if (!rules.has(ruleId)) {
|
|
267
|
+
tagRanges.push(new TagRange(0, stop, `exclusion:${ruleId}`));
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
rules.add(ruleId);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
return tagRanges;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
function storeSource({ type, name }) {
|
|
279
|
+
let storedSources = AsyncStorage.get(KEYS.SOURCES);
|
|
280
|
+
|
|
281
|
+
if (!storedSources) {
|
|
282
|
+
// if this is the first source stored on the request, initialize a map
|
|
283
|
+
// and set the storedSources to be a reference to the new, empty map.
|
|
284
|
+
storedSources = new Map();
|
|
285
|
+
AsyncStorage.set(KEYS.SOURCES, storedSources);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// there are cases where AsyncStorage context is out of sync, add defensive code so we don't
|
|
289
|
+
// crash.
|
|
290
|
+
if (storedSources) {
|
|
291
|
+
// save event for route coverage (data pulled in for RouteInfo object)
|
|
292
|
+
// only want to save unique values
|
|
293
|
+
storedSources.set(`${type}-${name}`, new TraceEventSource({ type, name }));
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
function logExclusionMessage(exclusion, type) {
|
|
298
|
+
const { name } = exclusion;
|
|
299
|
+
logger.debug(
|
|
300
|
+
'excluding %s inputs from all assess rules (%s)',
|
|
301
|
+
type.toLowerCase(),
|
|
302
|
+
name
|
|
303
|
+
);
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
module.exports.SourceEventHandler = SourceEventHandler;
|
|
307
|
+
module.exports.trackedObjects = trackedObjects;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
Copyright:
|
|
2
|
+
Copyright: 2022 Contrast Security, Inc
|
|
3
3
|
Contact: support@contrastsecurity.com
|
|
4
4
|
License: Commercial
|
|
5
5
|
|
|
@@ -26,9 +26,12 @@ const parseurl = require('parseurl');
|
|
|
26
26
|
const {
|
|
27
27
|
EXCLUSION_INPUT_TYPES: { BODY, HEADER, PARAMETER, QUERYSTRING, COOKIE }
|
|
28
28
|
} = require('../../constants');
|
|
29
|
+
const { Signature } = require('../models');
|
|
29
30
|
|
|
30
31
|
const sources = module.exports;
|
|
31
32
|
|
|
33
|
+
const { SourceEventHandler } = require('./event-handler');
|
|
34
|
+
|
|
32
35
|
/**
|
|
33
36
|
* Registers sources for assess instrumentation
|
|
34
37
|
*/
|
|
@@ -60,19 +63,104 @@ sources.track = function(type, parent, key, membrane) {
|
|
|
60
63
|
*/
|
|
61
64
|
sources.registerListeners = function({ config, exclusions }) {
|
|
62
65
|
agentEmitter.on('assess.body', (obj, prop) => {
|
|
63
|
-
|
|
66
|
+
if (!config.agent.traverse_and_track) {
|
|
67
|
+
return sources.handleSourceEvent(config, exclusions, BODY, obj, prop);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
agentEmitter.emit('assess.source', {
|
|
71
|
+
config,
|
|
72
|
+
exclusions,
|
|
73
|
+
obj,
|
|
74
|
+
prop,
|
|
75
|
+
data: obj[prop],
|
|
76
|
+
type: BODY
|
|
77
|
+
});
|
|
64
78
|
});
|
|
65
79
|
agentEmitter.on('assess.headers', (obj, prop) => {
|
|
66
|
-
|
|
80
|
+
if (!config.agent.traverse_and_track) {
|
|
81
|
+
return sources.handleSourceEvent(config, exclusions, HEADER, obj, prop);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
agentEmitter.emit('assess.source', {
|
|
85
|
+
obj,
|
|
86
|
+
prop,
|
|
87
|
+
data: obj[prop],
|
|
88
|
+
type: HEADER
|
|
89
|
+
});
|
|
67
90
|
});
|
|
68
91
|
agentEmitter.on('assess.params', (obj, prop) => {
|
|
69
|
-
|
|
92
|
+
if (!config.agent.traverse_and_track) {
|
|
93
|
+
return sources.handleSourceEvent(
|
|
94
|
+
config,
|
|
95
|
+
exclusions,
|
|
96
|
+
PARAMETER,
|
|
97
|
+
obj,
|
|
98
|
+
prop
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
agentEmitter.emit('assess.source', {
|
|
103
|
+
obj,
|
|
104
|
+
prop,
|
|
105
|
+
data: obj[prop],
|
|
106
|
+
type: PARAMETER
|
|
107
|
+
});
|
|
70
108
|
});
|
|
71
109
|
agentEmitter.on('assess.query', (obj, prop) => {
|
|
72
|
-
|
|
110
|
+
if (!config.agent.traverse_and_track) {
|
|
111
|
+
return sources.handleSourceEvent(
|
|
112
|
+
config,
|
|
113
|
+
exclusions,
|
|
114
|
+
QUERYSTRING,
|
|
115
|
+
obj,
|
|
116
|
+
prop
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
agentEmitter.emit('assess.source', {
|
|
121
|
+
obj,
|
|
122
|
+
prop,
|
|
123
|
+
data: obj[prop],
|
|
124
|
+
type: QUERYSTRING
|
|
125
|
+
});
|
|
73
126
|
});
|
|
127
|
+
|
|
74
128
|
agentEmitter.on('assess.cookies', (obj, prop) => {
|
|
75
|
-
|
|
129
|
+
if (!config.agent.traverse_and_track) {
|
|
130
|
+
return sources.handleSourceEvent(config, exclusions, COOKIE, obj, prop);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
agentEmitter.emit('assess.source', {
|
|
134
|
+
obj,
|
|
135
|
+
prop,
|
|
136
|
+
type: COOKIE
|
|
137
|
+
});
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
// might be helpful for clients to send add'l values in event arg
|
|
141
|
+
// - stackOpts: elide frames from function ref in client instrumentation
|
|
142
|
+
// - signature: rather than create shared one in the handler
|
|
143
|
+
// - or stack snapshot function - could share among SourceEvents
|
|
144
|
+
// - call context to share among SourceEvents
|
|
145
|
+
agentEmitter.on('assess.source', ({ obj, prop, type, signature }) => {
|
|
146
|
+
if (!signature) {
|
|
147
|
+
signature = new Signature({
|
|
148
|
+
moduleName: 'Object',
|
|
149
|
+
methodName: 'getter',
|
|
150
|
+
args: [prop],
|
|
151
|
+
return: 'String',
|
|
152
|
+
isModule: false
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
new SourceEventHandler({
|
|
157
|
+
config,
|
|
158
|
+
exclusions,
|
|
159
|
+
signature,
|
|
160
|
+
type,
|
|
161
|
+
stackOpts: undefined,
|
|
162
|
+
snapshot: undefined
|
|
163
|
+
}).handle({ obj, prop });
|
|
76
164
|
});
|
|
77
165
|
};
|
|
78
166
|
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
Copyright: 2022 Contrast Security, Inc
|
|
3
|
+
Contact: support@contrastsecurity.com
|
|
4
|
+
License: Commercial
|
|
5
|
+
|
|
6
|
+
NOTICE: This Software and the patented inventions embodied within may only be
|
|
7
|
+
used as part of Contrast Security’s commercial offerings. Even though it is
|
|
8
|
+
made available through public repositories, use of this Software is subject to
|
|
9
|
+
the applicable End User Licensing Agreement found at
|
|
10
|
+
https://www.contrastsecurity.com/enduser-terms-0317a or as otherwise agreed
|
|
11
|
+
between Contrast Security and the End User. The Software may not be reverse
|
|
12
|
+
engineered, modified, repackaged, sold, redistributed or otherwise used in a
|
|
13
|
+
way not consistent with the End User License Agreement.
|
|
14
|
+
*/
|
|
15
|
+
'use strict';
|
|
16
|
+
|
|
17
|
+
const AssessSinks = require('./sinks');
|
|
18
|
+
|
|
19
|
+
module.exports = class SpdyInstrumentation {
|
|
20
|
+
constructor(agent) {
|
|
21
|
+
new AssessSinks(agent);
|
|
22
|
+
}
|
|
23
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
Copyright: 2022 Contrast Security, Inc
|
|
3
|
+
Contact: support@contrastsecurity.com
|
|
4
|
+
License: Commercial
|
|
5
|
+
|
|
6
|
+
NOTICE: This Software and the patented inventions embodied within may only be
|
|
7
|
+
used as part of Contrast Security’s commercial offerings. Even though it is
|
|
8
|
+
made available through public repositories, use of this Software is subject to
|
|
9
|
+
the applicable End User Licensing Agreement found at
|
|
10
|
+
https://www.contrastsecurity.com/enduser-terms-0317a or as otherwise agreed
|
|
11
|
+
between Contrast Security and the End User. The Software may not be reverse
|
|
12
|
+
engineered, modified, repackaged, sold, redistributed or otherwise used in a
|
|
13
|
+
way not consistent with the End User License Agreement.
|
|
14
|
+
*/
|
|
15
|
+
'use strict';
|
|
16
|
+
|
|
17
|
+
const ReflectedXss = require('./xss');
|
|
18
|
+
|
|
19
|
+
module.exports = class SpdySinks {
|
|
20
|
+
constructor(agent) {
|
|
21
|
+
new ReflectedXss(agent);
|
|
22
|
+
}
|
|
23
|
+
};
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
Copyright: 2022 Contrast Security, Inc
|
|
3
|
+
Contact: support@contrastsecurity.com
|
|
4
|
+
License: Commercial
|
|
5
|
+
|
|
6
|
+
NOTICE: This Software and the patented inventions embodied within may only be
|
|
7
|
+
used as part of Contrast Security’s commercial offerings. Even though it is
|
|
8
|
+
made available through public repositories, use of this Software is subject to
|
|
9
|
+
the applicable End User Licensing Agreement found at
|
|
10
|
+
https://www.contrastsecurity.com/enduser-terms-0317a or as otherwise agreed
|
|
11
|
+
between Contrast Security and the End User. The Software may not be reverse
|
|
12
|
+
engineered, modified, repackaged, sold, redistributed or otherwise used in a
|
|
13
|
+
way not consistent with the End User License Agreement.
|
|
14
|
+
*/
|
|
15
|
+
'use strict';
|
|
16
|
+
|
|
17
|
+
const agentEmitter = require('../../../agent-emitter');
|
|
18
|
+
const { HTTP_RESPONSE_HOOKED_METHOD_KEYS } = require('../../../constants');
|
|
19
|
+
const policy = require('../../policy');
|
|
20
|
+
const { Signature, CallContext } = require('../../models');
|
|
21
|
+
|
|
22
|
+
class SpdyXss {
|
|
23
|
+
constructor(agent) {
|
|
24
|
+
this.common = require('../../sinks/common')(agent);
|
|
25
|
+
this.rules = policy.rules;
|
|
26
|
+
this.ruleId = 'reflected-xss';
|
|
27
|
+
this.signature = new Signature({
|
|
28
|
+
moduleName: 'spdy.response',
|
|
29
|
+
methodName: 'push',
|
|
30
|
+
isModule: false
|
|
31
|
+
});
|
|
32
|
+
agentEmitter.on(
|
|
33
|
+
HTTP_RESPONSE_HOOKED_METHOD_KEYS.PUSH,
|
|
34
|
+
this.checkResult.bind(this)
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* checks if an assess rule is enabled in policy
|
|
40
|
+
*/
|
|
41
|
+
get enabled() {
|
|
42
|
+
return (
|
|
43
|
+
this.rules &&
|
|
44
|
+
this.rules['reflected-xss'] &&
|
|
45
|
+
this.rules['reflected-xss'].enabled
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
checkResult(body) {
|
|
50
|
+
if (!this.enabled) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const { ruleId, signature } = this;
|
|
55
|
+
|
|
56
|
+
const {
|
|
57
|
+
isVulnerable,
|
|
58
|
+
xss: { disallowedTags },
|
|
59
|
+
requiredTags,
|
|
60
|
+
report
|
|
61
|
+
} = this.common;
|
|
62
|
+
|
|
63
|
+
if (
|
|
64
|
+
isVulnerable({
|
|
65
|
+
input: body,
|
|
66
|
+
disallowedTags,
|
|
67
|
+
requiredTags,
|
|
68
|
+
ruleId
|
|
69
|
+
})
|
|
70
|
+
) {
|
|
71
|
+
const ctxt = new CallContext({
|
|
72
|
+
obj: body,
|
|
73
|
+
args: [body],
|
|
74
|
+
result: body,
|
|
75
|
+
stackOpts: {
|
|
76
|
+
constructorOpt: agentEmitter.emit
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
report({ ruleId, signature, input: body, ctxt });
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
module.exports = SpdyXss;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
Copyright:
|
|
2
|
+
Copyright: 2022 Contrast Security, Inc
|
|
3
3
|
Contact: support@contrastsecurity.com
|
|
4
4
|
License: Commercial
|
|
5
5
|
|
|
@@ -31,7 +31,8 @@ const technologies = {
|
|
|
31
31
|
'fastify',
|
|
32
32
|
'restify',
|
|
33
33
|
'loopback',
|
|
34
|
-
'kraken-js'
|
|
34
|
+
'kraken-js',
|
|
35
|
+
'sails'
|
|
35
36
|
],
|
|
36
37
|
templating: ['jade', 'ejs', 'nunjucks', 'mustache', 'dust', 'handlebars'],
|
|
37
38
|
loggers: ['winston', 'debug'],
|
package/lib/assess/utils.js
CHANGED
package/lib/constants.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
Copyright:
|
|
2
|
+
Copyright: 2022 Contrast Security, Inc
|
|
3
3
|
Contact: support@contrastsecurity.com
|
|
4
4
|
License: Commercial
|
|
5
5
|
|
|
@@ -108,8 +108,11 @@ const RULES = {
|
|
|
108
108
|
'cmd-injection-semantic-chained-commands',
|
|
109
109
|
CMD_INJECTION_SEMANTIC_DANGEROUS_PATHS:
|
|
110
110
|
'cmd-injection-semantic-dangerous-paths',
|
|
111
|
-
IP_DENYLIST: 'ip-
|
|
111
|
+
IP_DENYLIST: 'ip-denylist',
|
|
112
112
|
METHOD_TAMPERING: 'method-tampering',
|
|
113
|
+
// The following is not a known rule in TS and is only used by SR when
|
|
114
|
+
// reporting certain analysis results. We convert to nosqli before reporting
|
|
115
|
+
NOSQL_EXPANSION: 'nosql-expansion',
|
|
113
116
|
NOSQL_INJECTION: 'nosql-injection',
|
|
114
117
|
PATH_TRAVERSAL: 'path-traversal',
|
|
115
118
|
REFLECTED_XSS: 'reflected-xss',
|
|
@@ -641,7 +644,8 @@ const REQUIRED_SIGNATURE_KEYS = [
|
|
|
641
644
|
|
|
642
645
|
const HTTP_RESPONSE_HOOKED_METHOD_KEYS = {
|
|
643
646
|
WRITE_HEAD: Symbol('writeHead'),
|
|
644
|
-
END: Symbol('end')
|
|
647
|
+
END: Symbol('end'),
|
|
648
|
+
PUSH: Symbol('push')
|
|
645
649
|
};
|
|
646
650
|
|
|
647
651
|
const PATCH_TYPES = {
|
package/lib/contrast.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
Copyright:
|
|
3
|
+
Copyright: 2022 Contrast Security, Inc
|
|
4
4
|
Contact: support@contrastsecurity.com
|
|
5
5
|
License: Commercial
|
|
6
6
|
|
|
@@ -178,7 +178,7 @@ contrastAgent.configureGlobalLogger = function(config, args, target = global) {
|
|
|
178
178
|
|
|
179
179
|
function getAgentArgs(options) {
|
|
180
180
|
const agentArgs = {};
|
|
181
|
-
|
|
181
|
+
program.options.forEach((opt) => {
|
|
182
182
|
if (opt.name() !== 'application.args' && options[opt.name()]) {
|
|
183
183
|
agentArgs[opt.name()] = options[opt.name()];
|
|
184
184
|
}
|
|
@@ -243,8 +243,8 @@ contrastAgent.prepare = function(...args) {
|
|
|
243
243
|
|
|
244
244
|
logger.info('Using config file at %s', config.configFile);
|
|
245
245
|
// log the argv before and after modification.
|
|
246
|
-
logger.info(`Original argv: ${
|
|
247
|
-
logger.info(`Modified argv: ${
|
|
246
|
+
logger.info(`Original argv: ${program.rawArgs.join(', ')}`);
|
|
247
|
+
logger.info(`Modified argv: ${program.args.join(', ')}`);
|
|
248
248
|
|
|
249
249
|
agent.config = config;
|
|
250
250
|
agent.tsFeatureSet.config = config;
|
|
@@ -335,12 +335,12 @@ contrastAgent.init = async function(args, isCli = false) {
|
|
|
335
335
|
// source: args passed to cli, destination: args after cli parsed it
|
|
336
336
|
.action(async function callPrepare(options, commanderArgs = []) {
|
|
337
337
|
// the user app main differs if a runner vs preload
|
|
338
|
-
script = isCli ?
|
|
338
|
+
script = isCli ? program.args[0] : program.rawArgs[1];
|
|
339
339
|
options.script = script;
|
|
340
340
|
// need to slice off app main in runner mode
|
|
341
341
|
options['application.args'] = isCli
|
|
342
|
-
?
|
|
343
|
-
:
|
|
342
|
+
? program.args.slice(1)
|
|
343
|
+
: program.args;
|
|
344
344
|
|
|
345
345
|
try {
|
|
346
346
|
enabled = await contrastAgent.prepare(options, commanderArgs, isCli);
|